blob: 277c45e72bcdf1aac80bfe6483743868c0196f35 [file] [log] [blame]
// 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_