| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_BROWSER_PERFORMANCE_MONITOR_PERFORMANCE_MONITOR_H_ |
| #define CHROME_BROWSER_PERFORMANCE_MONITOR_PERFORMANCE_MONITOR_H_ |
| |
| #include <map> |
| #include <set> |
| #include <string> |
| |
| #include "base/files/file_path.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/process/process_handle.h" |
| #include "base/time/time.h" |
| #include "base/timer/timer.h" |
| #include "chrome/browser/performance_monitor/event_type.h" |
| #include "chrome/browser/performance_monitor/process_metrics_history.h" |
| #include "content/public/browser/notification_observer.h" |
| #include "content/public/browser/notification_registrar.h" |
| #include "content/public/browser/render_process_host.h" |
| |
| template <typename Type> |
| struct DefaultSingletonTraits; |
| |
| namespace extensions { |
| class Extension; |
| } |
| |
| namespace net { |
| class URLRequest; |
| } |
| |
| namespace performance_monitor { |
| class Database; |
| class Event; |
| struct Metric; |
| |
| // PerformanceMonitor is a tool which will allow the user to view information |
| // about Chrome's performance over a period of time. It will gather statistics |
| // pertaining to performance-oriented areas (e.g. CPU usage, memory usage, and |
| // network usage) and will also store information about significant events which |
| // are related to performance, either being indicative (e.g. crashes) or |
| // potentially causal (e.g. extension installation/uninstallation). |
| // |
| // Thread Safety: PerformanceMonitor lives on multiple threads. When interacting |
| // with the Database, PerformanceMonitor acts on a background thread (which has |
| // the sequence guaranteed by a token, Database::kDatabaseSequenceToken). At |
| // other times, the PerformanceMonitor will act on the appropriate thread for |
| // the task (for instance, gathering statistics about CPU and memory usage |
| // is done on the background thread, but most notifications occur on the UI |
| // thread). |
| class PerformanceMonitor : public content::NotificationObserver { |
| public: |
| struct PerformanceDataForIOThread { |
| PerformanceDataForIOThread(); |
| |
| uint64 network_bytes_read; |
| }; |
| |
| typedef std::map<base::ProcessHandle, ProcessMetricsHistory> MetricsMap; |
| |
| // Set the path which the PerformanceMonitor should use for the database files |
| // constructed. This must be done prior to the initialization of the |
| // PerformanceMonitor. Returns true on success, false on failure (failure |
| // likely indicates that PerformanceMonitor has already been started at the |
| // time of the call). |
| bool SetDatabasePath(const base::FilePath& path); |
| |
| bool database_logging_enabled() const { return database_logging_enabled_; } |
| |
| // Returns the current PerformanceMonitor instance if one exists; otherwise |
| // constructs a new PerformanceMonitor. |
| static PerformanceMonitor* GetInstance(); |
| |
| // Begins the initialization process for the PerformanceMonitor in order to |
| // start collecting data. |
| void Initialize(); |
| |
| // Start the cycle of metrics gathering. |
| void StartGatherCycle(); |
| |
| // Inform PerformanceMonitor that bytes have been read; if these came across |
| // the network (and PerformanceMonitor is initialized), then increment the |
| // count accordingly. |
| void BytesReadOnIOThread(const net::URLRequest& request, const int bytes); |
| |
| // content::NotificationObserver |
| // Wait for various notifications; insert events into the database upon |
| // occurance. |
| virtual void Observe(int type, |
| const content::NotificationSource& source, |
| const content::NotificationDetails& details) OVERRIDE; |
| |
| Database* database() { return database_.get(); } |
| base::FilePath database_path() { return database_path_; } |
| static bool initialized() { return initialized_; } |
| |
| private: |
| friend struct DefaultSingletonTraits<PerformanceMonitor>; |
| friend class PerformanceMonitorBrowserTest; |
| FRIEND_TEST_ALL_PREFIXES(PerformanceMonitorUncleanExitBrowserTest, |
| OneProfileUncleanExit); |
| FRIEND_TEST_ALL_PREFIXES(PerformanceMonitorUncleanExitBrowserTest, |
| TwoProfileUncleanExit); |
| FRIEND_TEST_ALL_PREFIXES(PerformanceMonitorBrowserTest, NetworkBytesRead); |
| |
| PerformanceMonitor(); |
| virtual ~PerformanceMonitor(); |
| |
| // Perform any additional initialization which must be performed on a |
| // background thread (e.g. constructing the database). |
| void InitOnBackgroundThread(); |
| |
| void FinishInit(); |
| |
| // Create the persistent database if we haven't already done so. |
| void InitializeDatabaseIfNeeded(); |
| |
| // Register for the appropriate notifications as a NotificationObserver. |
| void RegisterForNotifications(); |
| |
| // Checks for whether the previous profiles closed uncleanly; this method |
| // should only be called once per run in order to avoid duplication of events |
| // (exceptions made for testing purposes where we construct the environment). |
| void CheckForUncleanExits(); |
| |
| // Find the last active time for the profile and insert the event into the |
| // database. |
| void AddUncleanExitEventOnBackgroundThread(const std::string& profile_name); |
| |
| // Check the previous Chrome version from the Database and determine if |
| // it has been updated. If it has, insert an event in the database. |
| void CheckForVersionUpdateOnBackgroundThread(); |
| |
| // Wrapper function for inserting events into the database. |
| void AddEvent(scoped_ptr<Event> event); |
| |
| void AddEventOnBackgroundThread(scoped_ptr<Event> event); |
| |
| // Since Database::AddMetric() is overloaded, base::Bind() does not work and |
| // we need a helper function. |
| void AddMetricOnBackgroundThread(const Metric& metric); |
| |
| // Notify any listeners that PerformanceMonitor has finished the initializing. |
| void NotifyInitialized(); |
| |
| // Perform any collections that are done on a timed basis. |
| void DoTimedCollections(); |
| |
| // Update the database record of the last time the active profiles were |
| // running; this is used in determining when an unclean exit occurred. |
| #if !defined(OS_ANDROID) |
| void UpdateLiveProfiles(); |
| void UpdateLiveProfilesHelper( |
| scoped_ptr<std::set<std::string> > active_profiles, std::string time); |
| #endif |
| |
| // Stores CPU/memory usage metrics to the database. |
| void StoreMetricsOnBackgroundThread( |
| int current_update_sequence, |
| const PerformanceDataForIOThread& performance_data_for_io_thread); |
| |
| // Mark the given process as alive in the current update iteration. |
| // This means adding an entry to the map of watched processes if it's not |
| // already present. |
| void MarkProcessAsAlive(const base::ProcessHandle& handle, |
| int process_type, |
| int current_update_sequence); |
| |
| // Updates the ProcessMetrics map with the current list of processes and |
| // gathers metrics from each entry. |
| void GatherMetricsMapOnUIThread(); |
| void GatherMetricsMapOnIOThread(int current_update_sequence); |
| |
| // Generate an appropriate ExtensionEvent for an extension-related occurrance |
| // and insert it in the database. |
| void AddExtensionEvent(EventType type, |
| const extensions::Extension* extension); |
| |
| // Generate an appropriate RendererFailure for a renderer crash and insert it |
| // in the database. |
| void AddRendererClosedEvent( |
| content::RenderProcessHost* host, |
| const content::RenderProcessHost::RendererClosedDetails& details); |
| |
| // The store for all performance data that must be gathered from the IO |
| // thread. |
| PerformanceDataForIOThread performance_data_for_io_thread_; |
| |
| // The location at which the database files are stored; if empty, the database |
| // will default to '<user_data_dir>/performance_monitor_dbs'. |
| base::FilePath database_path_; |
| |
| scoped_ptr<Database> database_; |
| |
| // A map of currently running ProcessHandles to ProcessMetrics. |
| MetricsMap metrics_map_; |
| |
| // The next time we should collect averages from the performance metrics |
| // and act on them. |
| base::Time next_collection_time_; |
| |
| // How long to wait between collections. |
| int gather_interval_in_seconds_; |
| |
| // Enable persistent logging of performance metrics to a database. |
| bool database_logging_enabled_; |
| |
| // The timer to signal PerformanceMonitor to perform its timed collections. |
| base::DelayTimer<PerformanceMonitor> timer_; |
| |
| content::NotificationRegistrar registrar_; |
| |
| // A flag indicating whether or not PerformanceMonitor is initialized. Any |
| // external sources accessing PerformanceMonitor should either wait for |
| // the PERFORMANCE_MONITOR_INITIALIZED notification or should check this |
| // flag. |
| static bool initialized_; |
| |
| // Disable auto-starting the collection timer; used for tests. |
| bool disable_timer_autostart_for_testing_; |
| |
| DISALLOW_COPY_AND_ASSIGN(PerformanceMonitor); |
| }; |
| |
| } // namespace performance_monitor |
| |
| #endif // CHROME_BROWSER_PERFORMANCE_MONITOR_PERFORMANCE_MONITOR_H_ |