root/chrome/browser/performance_monitor/performance_monitor.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


// 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_

/* [<][>][^][v][top][bottom][index][help] */