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.
5 #ifndef CHROME_BROWSER_PERFORMANCE_MONITOR_PERFORMANCE_MONITOR_H_
6 #define CHROME_BROWSER_PERFORMANCE_MONITOR_PERFORMANCE_MONITOR_H_
12 #include "base/files/file_path.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/process/process_handle.h"
15 #include "base/time/time.h"
16 #include "base/timer/timer.h"
17 #include "chrome/browser/performance_monitor/event_type.h"
18 #include "chrome/browser/performance_monitor/process_metrics_history.h"
19 #include "content/public/browser/notification_observer.h"
20 #include "content/public/browser/notification_registrar.h"
21 #include "content/public/browser/render_process_host.h"
23 template <typename Type
>
24 struct DefaultSingletonTraits
;
26 namespace extensions
{
34 namespace performance_monitor
{
39 // PerformanceMonitor is a tool which will allow the user to view information
40 // about Chrome's performance over a period of time. It will gather statistics
41 // pertaining to performance-oriented areas (e.g. CPU usage, memory usage, and
42 // network usage) and will also store information about significant events which
43 // are related to performance, either being indicative (e.g. crashes) or
44 // potentially causal (e.g. extension installation/uninstallation).
46 // Thread Safety: PerformanceMonitor lives on multiple threads. When interacting
47 // with the Database, PerformanceMonitor acts on a background thread (which has
48 // the sequence guaranteed by a token, Database::kDatabaseSequenceToken). At
49 // other times, the PerformanceMonitor will act on the appropriate thread for
50 // the task (for instance, gathering statistics about CPU and memory usage
51 // is done on the background thread, but most notifications occur on the UI
53 class PerformanceMonitor
: public content::NotificationObserver
{
55 struct PerformanceDataForIOThread
{
56 PerformanceDataForIOThread();
58 uint64 network_bytes_read
;
61 typedef std::map
<base::ProcessHandle
, ProcessMetricsHistory
> MetricsMap
;
63 // Set the path which the PerformanceMonitor should use for the database files
64 // constructed. This must be done prior to the initialization of the
65 // PerformanceMonitor. Returns true on success, false on failure (failure
66 // likely indicates that PerformanceMonitor has already been started at the
68 bool SetDatabasePath(const base::FilePath
& path
);
70 bool database_logging_enabled() const { return database_logging_enabled_
; }
72 // Returns the current PerformanceMonitor instance if one exists; otherwise
73 // constructs a new PerformanceMonitor.
74 static PerformanceMonitor
* GetInstance();
76 // Begins the initialization process for the PerformanceMonitor in order to
77 // start collecting data.
80 // Start the cycle of metrics gathering.
81 void StartGatherCycle();
83 // Inform PerformanceMonitor that bytes have been read; if these came across
84 // the network (and PerformanceMonitor is initialized), then increment the
86 void BytesReadOnIOThread(const net::URLRequest
& request
, const int bytes
);
88 // content::NotificationObserver
89 // Wait for various notifications; insert events into the database upon
91 virtual void Observe(int type
,
92 const content::NotificationSource
& source
,
93 const content::NotificationDetails
& details
) OVERRIDE
;
95 Database
* database() { return database_
.get(); }
96 base::FilePath
database_path() { return database_path_
; }
97 static bool initialized() { return initialized_
; }
100 friend struct DefaultSingletonTraits
<PerformanceMonitor
>;
101 friend class PerformanceMonitorBrowserTest
;
102 FRIEND_TEST_ALL_PREFIXES(PerformanceMonitorUncleanExitBrowserTest
,
103 OneProfileUncleanExit
);
104 FRIEND_TEST_ALL_PREFIXES(PerformanceMonitorUncleanExitBrowserTest
,
105 TwoProfileUncleanExit
);
106 FRIEND_TEST_ALL_PREFIXES(PerformanceMonitorBrowserTest
, NetworkBytesRead
);
108 PerformanceMonitor();
109 virtual ~PerformanceMonitor();
111 // Perform any additional initialization which must be performed on a
112 // background thread (e.g. constructing the database).
113 void InitOnBackgroundThread();
117 // Create the persistent database if we haven't already done so.
118 void InitializeDatabaseIfNeeded();
120 // Register for the appropriate notifications as a NotificationObserver.
121 void RegisterForNotifications();
123 // Checks for whether the previous profiles closed uncleanly; this method
124 // should only be called once per run in order to avoid duplication of events
125 // (exceptions made for testing purposes where we construct the environment).
126 void CheckForUncleanExits();
128 // Find the last active time for the profile and insert the event into the
130 void AddUncleanExitEventOnBackgroundThread(const std::string
& profile_name
);
132 // Check the previous Chrome version from the Database and determine if
133 // it has been updated. If it has, insert an event in the database.
134 void CheckForVersionUpdateOnBackgroundThread();
136 // Wrapper function for inserting events into the database.
137 void AddEvent(scoped_ptr
<Event
> event
);
139 void AddEventOnBackgroundThread(scoped_ptr
<Event
> event
);
141 // Since Database::AddMetric() is overloaded, base::Bind() does not work and
142 // we need a helper function.
143 void AddMetricOnBackgroundThread(const Metric
& metric
);
145 // Notify any listeners that PerformanceMonitor has finished the initializing.
146 void NotifyInitialized();
148 // Perform any collections that are done on a timed basis.
149 void DoTimedCollections();
151 // Update the database record of the last time the active profiles were
152 // running; this is used in determining when an unclean exit occurred.
153 #if !defined(OS_ANDROID)
154 void UpdateLiveProfiles();
155 void UpdateLiveProfilesHelper(
156 scoped_ptr
<std::set
<std::string
> > active_profiles
, std::string time
);
159 // Stores CPU/memory usage metrics to the database.
160 void StoreMetricsOnBackgroundThread(
161 int current_update_sequence
,
162 const PerformanceDataForIOThread
& performance_data_for_io_thread
);
164 // Mark the given process as alive in the current update iteration.
165 // This means adding an entry to the map of watched processes if it's not
167 void MarkProcessAsAlive(const base::ProcessHandle
& handle
,
169 int current_update_sequence
);
171 // Updates the ProcessMetrics map with the current list of processes and
172 // gathers metrics from each entry.
173 void GatherMetricsMapOnUIThread();
174 void GatherMetricsMapOnIOThread(int current_update_sequence
);
176 // Generate an appropriate ExtensionEvent for an extension-related occurrance
177 // and insert it in the database.
178 void AddExtensionEvent(EventType type
,
179 const extensions::Extension
* extension
);
181 // Generate an appropriate RendererFailure for a renderer crash and insert it
183 void AddRendererClosedEvent(
184 content::RenderProcessHost
* host
,
185 const content::RenderProcessHost::RendererClosedDetails
& details
);
187 // The store for all performance data that must be gathered from the IO
189 PerformanceDataForIOThread performance_data_for_io_thread_
;
191 // The location at which the database files are stored; if empty, the database
192 // will default to '<user_data_dir>/performance_monitor_dbs'.
193 base::FilePath database_path_
;
195 scoped_ptr
<Database
> database_
;
197 // A map of currently running ProcessHandles to ProcessMetrics.
198 MetricsMap metrics_map_
;
200 // The next time we should collect averages from the performance metrics
202 base::Time next_collection_time_
;
204 // How long to wait between collections.
205 int gather_interval_in_seconds_
;
207 // Enable persistent logging of performance metrics to a database.
208 bool database_logging_enabled_
;
210 // The timer to signal PerformanceMonitor to perform its timed collections.
211 base::DelayTimer
<PerformanceMonitor
> timer_
;
213 content::NotificationRegistrar registrar_
;
215 // A flag indicating whether or not PerformanceMonitor is initialized. Any
216 // external sources accessing PerformanceMonitor should either wait for
217 // the PERFORMANCE_MONITOR_INITIALIZED notification or should check this
219 static bool initialized_
;
221 // Disable auto-starting the collection timer; used for tests.
222 bool disable_timer_autostart_for_testing_
;
224 DISALLOW_COPY_AND_ASSIGN(PerformanceMonitor
);
227 } // namespace performance_monitor
229 #endif // CHROME_BROWSER_PERFORMANCE_MONITOR_PERFORMANCE_MONITOR_H_