Home | History | Annotate | Download | only in performance_monitor
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef CHROME_BROWSER_PERFORMANCE_MONITOR_PERFORMANCE_MONITOR_H_
      6 #define CHROME_BROWSER_PERFORMANCE_MONITOR_PERFORMANCE_MONITOR_H_
      7 
      8 #include <map>
      9 #include <string>
     10 
     11 #include "base/callback.h"
     12 #include "base/files/file_path.h"
     13 #include "base/memory/linked_ptr.h"
     14 #include "base/memory/scoped_ptr.h"
     15 #include "base/memory/singleton.h"
     16 #include "base/process/process_metrics.h"
     17 #include "base/timer/timer.h"
     18 #include "chrome/browser/performance_monitor/database.h"
     19 #include "chrome/browser/performance_monitor/event.h"
     20 #include "content/public/browser/notification_details.h"
     21 #include "content/public/browser/notification_observer.h"
     22 #include "content/public/browser/notification_registrar.h"
     23 #include "content/public/browser/notification_source.h"
     24 #include "content/public/browser/render_process_host.h"
     25 
     26 namespace extensions {
     27 class Extension;
     28 }
     29 
     30 namespace net {
     31 class URLRequest;
     32 }
     33 
     34 namespace performance_monitor {
     35 class Database;
     36 
     37 // PerformanceMonitor is a tool which will allow the user to view information
     38 // about Chrome's performance over a period of time. It will gather statistics
     39 // pertaining to performance-oriented areas (e.g. CPU usage, memory usage, and
     40 // network usage) and will also store information about significant events which
     41 // are related to performance, either being indicative (e.g. crashes) or
     42 // potentially causal (e.g. extension installation/uninstallation).
     43 //
     44 // Thread Safety: PerformanceMonitor lives on multiple threads. When interacting
     45 // with the Database, PerformanceMonitor acts on a background thread (which has
     46 // the sequence guaranteed by a token, Database::kDatabaseSequenceToken). At
     47 // other times, the PerformanceMonitor will act on the appropriate thread for
     48 // the task (for instance, gathering statistics about CPU and memory usage
     49 // is done on the background thread, but most notifications occur on the UI
     50 // thread).
     51 class PerformanceMonitor : public content::NotificationObserver {
     52  public:
     53   struct PerformanceDataForIOThread {
     54     PerformanceDataForIOThread();
     55 
     56     uint64 network_bytes_read;
     57   };
     58 
     59   typedef std::map<base::ProcessHandle,
     60                    linked_ptr<base::ProcessMetrics> > MetricsMap;
     61 
     62   // Set the path which the PerformanceMonitor should use for the database files
     63   // constructed. This must be done prior to the initialization of the
     64   // PerformanceMonitor. Returns true on success, false on failure (failure
     65   // likely indicates that PerformanceMonitor has already been started at the
     66   // time of the call).
     67   bool SetDatabasePath(const base::FilePath& path);
     68 
     69   // Returns the current PerformanceMonitor instance if one exists; otherwise
     70   // constructs a new PerformanceMonitor.
     71   static PerformanceMonitor* GetInstance();
     72 
     73   // Begins the initialization process for the PerformanceMonitor in order to
     74   // start collecting data.
     75   void Start();
     76 
     77   // Inform PerformanceMonitor that bytes have been read; if these came across
     78   // the network (and PerformanceMonitor is initialized), then increment the
     79   // count accordingly.
     80   void BytesReadOnIOThread(const net::URLRequest& request, const int bytes);
     81 
     82   // content::NotificationObserver
     83   // Wait for various notifications; insert events into the database upon
     84   // occurance.
     85   virtual void Observe(int type,
     86                        const content::NotificationSource& source,
     87                        const content::NotificationDetails& details) OVERRIDE;
     88 
     89   Database* database() { return database_.get(); }
     90   base::FilePath database_path() { return database_path_; }
     91   static bool initialized() { return initialized_; }
     92 
     93  private:
     94   friend struct DefaultSingletonTraits<PerformanceMonitor>;
     95   friend class PerformanceMonitorBrowserTest;
     96   FRIEND_TEST_ALL_PREFIXES(PerformanceMonitorUncleanExitBrowserTest,
     97                            OneProfileUncleanExit);
     98   FRIEND_TEST_ALL_PREFIXES(PerformanceMonitorUncleanExitBrowserTest,
     99                            TwoProfileUncleanExit);
    100   FRIEND_TEST_ALL_PREFIXES(PerformanceMonitorBrowserTest, NetworkBytesRead);
    101 
    102   PerformanceMonitor();
    103   virtual ~PerformanceMonitor();
    104 
    105   // Perform any additional initialization which must be performed on a
    106   // background thread (e.g. constructing the database).
    107   void InitOnBackgroundThread();
    108 
    109   void FinishInit();
    110 
    111   // Register for the appropriate notifications as a NotificationObserver.
    112   void RegisterForNotifications();
    113 
    114   // Checks for whether the previous profiles closed uncleanly; this method
    115   // should only be called once per run in order to avoid duplication of events
    116   // (exceptions made for testing purposes where we construct the environment).
    117   void CheckForUncleanExits();
    118 
    119   // Find the last active time for the profile and insert the event into the
    120   // database.
    121   void AddUncleanExitEventOnBackgroundThread(const std::string& profile_name);
    122 
    123   // Check the previous Chrome version from the Database and determine if
    124   // it has been updated. If it has, insert an event in the database.
    125   void CheckForVersionUpdateOnBackgroundThread();
    126 
    127   // Wrapper function for inserting events into the database.
    128   void AddEvent(scoped_ptr<Event> event);
    129 
    130   void AddEventOnBackgroundThread(scoped_ptr<Event> event);
    131 
    132   // Since Database::AddMetric() is overloaded, base::Bind() does not work and
    133   // we need a helper function.
    134   void AddMetricOnBackgroundThread(const Metric& metric);
    135 
    136   // Notify any listeners that PerformanceMonitor has finished the initializing.
    137   void NotifyInitialized();
    138 
    139   // Perform any collections that are done on a timed basis.
    140   void DoTimedCollections();
    141 
    142   // Update the database record of the last time the active profiles were
    143   // running; this is used in determining when an unclean exit occurred.
    144   void UpdateLiveProfiles();
    145   void UpdateLiveProfilesHelper(
    146       scoped_ptr<std::set<std::string> > active_profiles, std::string time);
    147 
    148   // Gathers CPU usage and memory usage of all Chrome processes in order to.
    149   void GatherStatisticsOnBackgroundThread();
    150 
    151   // Gathers the CPU usage of every Chrome process that has been running since
    152   // the last call to GatherStatistics().
    153   void GatherCPUUsageOnBackgroundThread();
    154 
    155   // Gathers the memory usage of every process in the current list of processes.
    156   void GatherMemoryUsageOnBackgroundThread();
    157 
    158   // Updates the ProcessMetrics map with the current list of processes.
    159   void UpdateMetricsMapOnBackgroundThread();
    160 
    161   // Generate an appropriate ExtensionEvent for an extension-related occurrance
    162   // and insert it in the database.
    163   void AddExtensionEvent(EventType type,
    164                          const extensions::Extension* extension);
    165 
    166   // Generate an appropriate RendererFailure for a renderer crash and insert it
    167   // in the database.
    168   void AddRendererClosedEvent(
    169       content::RenderProcessHost* host,
    170       const content::RenderProcessHost::RendererClosedDetails& details);
    171 
    172   // Called on the IO thread, this will call InsertIOData on the background
    173   // thread with a copy of the PerformanceDataForIOThread object to prevent
    174   // any possible race conditions.
    175   void CallInsertIOData();
    176 
    177   // Insert the collected IO data into the database.
    178   void InsertIOData(
    179       const PerformanceDataForIOThread& performance_data_for_io_thread);
    180 
    181   // The store for all performance data that must be gathered from the IO
    182   // thread.
    183   PerformanceDataForIOThread performance_data_for_io_thread_;
    184 
    185   // The location at which the database files are stored; if empty, the database
    186   // will default to '<user_data_dir>/performance_monitor_dbs'.
    187   base::FilePath database_path_;
    188 
    189   scoped_ptr<Database> database_;
    190 
    191   // A map of currently running ProcessHandles to ProcessMetrics.
    192   scoped_ptr<MetricsMap> metrics_map_;
    193 
    194   // The timer to signal PerformanceMonitor to perform its timed collections.
    195   base::RepeatingTimer<PerformanceMonitor> timer_;
    196 
    197   content::NotificationRegistrar registrar_;
    198 
    199   // A flag indicating whether or not PerformanceMonitor is initialized. Any
    200   // external sources accessing PerformanceMonitor should either wait for
    201   // the PERFORMANCE_MONITOR_INITIALIZED notification or should check this
    202   // flag.
    203   static bool initialized_;
    204 
    205   DISALLOW_COPY_AND_ASSIGN(PerformanceMonitor);
    206 };
    207 
    208 }  // namespace performance_monitor
    209 
    210 #endif  // CHROME_BROWSER_PERFORMANCE_MONITOR_PERFORMANCE_MONITOR_H_
    211