summaryrefslogtreecommitdiffstats
path: root/components/metrics/metrics_service.h
diff options
context:
space:
mode:
Diffstat (limited to 'components/metrics/metrics_service.h')
-rw-r--r--components/metrics/metrics_service.h468
1 files changed, 468 insertions, 0 deletions
diff --git a/components/metrics/metrics_service.h b/components/metrics/metrics_service.h
new file mode 100644
index 0000000..b586263
--- /dev/null
+++ b/components/metrics/metrics_service.h
@@ -0,0 +1,468 @@
+// Copyright 2014 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.
+
+// This file defines a service that collects information about the user
+// experience in order to help improve future versions of the app.
+
+#ifndef COMPONENTS_METRICS_METRICS_SERVICE_H_
+#define COMPONENTS_METRICS_METRICS_SERVICE_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "base/memory/weak_ptr.h"
+#include "base/metrics/field_trial.h"
+#include "base/metrics/histogram_flattener.h"
+#include "base/metrics/histogram_snapshot_manager.h"
+#include "base/metrics/user_metrics.h"
+#include "base/observer_list.h"
+#include "base/strings/string16.h"
+#include "base/threading/thread_checker.h"
+#include "base/time/time.h"
+#include "components/metrics/metrics_log.h"
+#include "components/metrics/metrics_log_manager.h"
+#include "components/metrics/metrics_provider.h"
+#include "components/metrics/metrics_service_observer.h"
+#include "components/variations/active_field_trials.h"
+
+class MetricsReportingScheduler;
+class PrefService;
+class PrefRegistrySimple;
+
+namespace base {
+class DictionaryValue;
+class HistogramSamples;
+class MessageLoopProxy;
+class PrefService;
+}
+
+namespace variations {
+struct ActiveGroupId;
+}
+
+namespace metrics {
+class MetricsLogUploader;
+class MetricsServiceClient;
+class MetricsStateManager;
+}
+
+namespace net {
+class URLFetcher;
+}
+
+// A Field Trial and its selected group, which represent a particular
+// Chrome configuration state. For example, the trial name could map to
+// a preference name, and the group name could map to a preference value.
+struct SyntheticTrialGroup {
+ public:
+ ~SyntheticTrialGroup();
+
+ variations::ActiveGroupId id;
+ base::TimeTicks start_time;
+
+ private:
+ friend class MetricsService;
+ FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, RegisterSyntheticTrial);
+
+ // This constructor is private specifically so as to control which code is
+ // able to access it. New code that wishes to use it should be added as a
+ // friend class.
+ SyntheticTrialGroup(uint32 trial, uint32 group);
+};
+
+class MetricsService : public base::HistogramFlattener {
+ public:
+ // The execution phase of the browser.
+ enum ExecutionPhase {
+ UNINITIALIZED_PHASE = 0,
+ START_METRICS_RECORDING = 100,
+ CREATE_PROFILE = 200,
+ STARTUP_TIMEBOMB_ARM = 300,
+ THREAD_WATCHER_START = 400,
+ MAIN_MESSAGE_LOOP_RUN = 500,
+ SHUTDOWN_TIMEBOMB_ARM = 600,
+ SHUTDOWN_COMPLETE = 700,
+ };
+
+ // Creates the MetricsService with the given |state_manager|, |client|, and
+ // |local_state|. Does not take ownership of the paramaters; instead stores
+ // a weak pointer to each. Caller should ensure that the parameters are valid
+ // for the lifetime of this class.
+ MetricsService(metrics::MetricsStateManager* state_manager,
+ metrics::MetricsServiceClient* client,
+ PrefService* local_state);
+ virtual ~MetricsService();
+
+ // Initializes metrics recording state. Updates various bookkeeping values in
+ // prefs and sets up the scheduler. This is a separate function rather than
+ // being done by the constructor so that field trials could be created before
+ // this is run.
+ void InitializeMetricsRecordingState();
+
+ // Starts the metrics system, turning on recording and uploading of metrics.
+ // Should be called when starting up with metrics enabled, or when metrics
+ // are turned on.
+ void Start();
+
+ // If metrics reporting is enabled, starts the metrics service. Returns
+ // whether the metrics service was started.
+ bool StartIfMetricsReportingEnabled();
+
+ // Starts the metrics system in a special test-only mode. Metrics won't ever
+ // be uploaded or persisted in this mode, but metrics will be recorded in
+ // memory.
+ void StartRecordingForTests();
+
+ // Shuts down the metrics system. Should be called at shutdown, or if metrics
+ // are turned off.
+ void Stop();
+
+ // Enable/disable transmission of accumulated logs and crash reports (dumps).
+ // Calling Start() automatically enables reporting, but sending is
+ // asyncronous so this can be called immediately after Start() to prevent
+ // any uploading.
+ void EnableReporting();
+ void DisableReporting();
+
+ // Returns the client ID for this client, or the empty string if metrics
+ // recording is not currently running.
+ std::string GetClientId();
+
+ // Returns the preferred entropy provider used to seed persistent activities
+ // based on whether or not metrics reporting will be permitted on this client.
+ //
+ // If metrics reporting is enabled, this method returns an entropy provider
+ // that has a high source of entropy, partially based on the client ID.
+ // Otherwise, it returns an entropy provider that is based on a low entropy
+ // source.
+ scoped_ptr<const base::FieldTrial::EntropyProvider> CreateEntropyProvider();
+
+ // At startup, prefs needs to be called with a list of all the pref names and
+ // types we'll be using.
+ static void RegisterPrefs(PrefRegistrySimple* registry);
+
+ // HistogramFlattener:
+ virtual void RecordDelta(const base::HistogramBase& histogram,
+ const base::HistogramSamples& snapshot) OVERRIDE;
+ virtual void InconsistencyDetected(
+ base::HistogramBase::Inconsistency problem) OVERRIDE;
+ virtual void UniqueInconsistencyDetected(
+ base::HistogramBase::Inconsistency problem) OVERRIDE;
+ virtual void InconsistencyDetectedInLoggedCount(int amount) OVERRIDE;
+
+ // This should be called when the application is not idle, i.e. the user seems
+ // to be interacting with the application.
+ void OnApplicationNotIdle();
+
+ // Invoked when we get a WM_SESSIONEND. This places a value in prefs that is
+ // reset when RecordCompletedSessionEnd is invoked.
+ void RecordStartOfSessionEnd();
+
+ // This should be called when the application is shutting down. It records
+ // that session end was successful.
+ void RecordCompletedSessionEnd();
+
+#if defined(OS_ANDROID) || defined(OS_IOS)
+ // Called when the application is going into background mode.
+ void OnAppEnterBackground();
+
+ // Called when the application is coming out of background mode.
+ void OnAppEnterForeground();
+#else
+ // Set the dirty flag, which will require a later call to LogCleanShutdown().
+ static void LogNeedForCleanShutdown(PrefService* local_state);
+#endif // defined(OS_ANDROID) || defined(OS_IOS)
+
+ static void SetExecutionPhase(ExecutionPhase execution_phase,
+ PrefService* local_state);
+
+ // Saves in the preferences if the crash report registration was successful.
+ // This count is eventually send via UMA logs.
+ void RecordBreakpadRegistration(bool success);
+
+ // Saves in the preferences if the browser is running under a debugger.
+ // This count is eventually send via UMA logs.
+ void RecordBreakpadHasDebugger(bool has_debugger);
+
+ bool recording_active() const;
+ bool reporting_active() const;
+
+ // Redundant test to ensure that we are notified of a clean exit.
+ // This value should be true when process has completed shutdown.
+ static bool UmaMetricsProperlyShutdown();
+
+ // Registers a field trial name and group to be used to annotate a UMA report
+ // with a particular Chrome configuration state. A UMA report will be
+ // annotated with this trial group if and only if all events in the report
+ // were created after the trial is registered. Only one group name may be
+ // registered at a time for a given trial_name. Only the last group name that
+ // is registered for a given trial name will be recorded. The values passed
+ // in must not correspond to any real field trial in the code.
+ // To use this method, SyntheticTrialGroup should friend your class.
+ void RegisterSyntheticFieldTrial(const SyntheticTrialGroup& trial_group);
+
+ // Register the specified |provider| to provide additional metrics into the
+ // UMA log. Should be called during MetricsService initialization only.
+ void RegisterMetricsProvider(scoped_ptr<metrics::MetricsProvider> provider);
+
+ // Check if this install was cloned or imaged from another machine. If a
+ // clone is detected, reset the client id and low entropy source. This
+ // should not be called more than once.
+ void CheckForClonedInstall(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
+ protected:
+ // Exposed for testing.
+ metrics::MetricsLogManager* log_manager() { return &log_manager_; }
+
+ private:
+ // The MetricsService has a lifecycle that is stored as a state.
+ // See metrics_service.cc for description of this lifecycle.
+ enum State {
+ INITIALIZED, // Constructor was called.
+ INIT_TASK_SCHEDULED, // Waiting for deferred init tasks to
+ // complete.
+ INIT_TASK_DONE, // Waiting for timer to send initial log.
+ SENDING_INITIAL_STABILITY_LOG, // Initial stability log being sent.
+ SENDING_INITIAL_METRICS_LOG, // Initial metrics log being sent.
+ SENDING_OLD_LOGS, // Sending unsent logs from last session.
+ SENDING_CURRENT_LOGS, // Sending ongoing logs as they accrue.
+ };
+
+ enum ShutdownCleanliness {
+ CLEANLY_SHUTDOWN = 0xdeadbeef,
+ NEED_TO_SHUTDOWN = ~CLEANLY_SHUTDOWN
+ };
+
+ typedef std::vector<SyntheticTrialGroup> SyntheticTrialGroups;
+
+ // Calls into the client to start metrics gathering.
+ void StartGatheringMetrics();
+
+ // Callback that moves the state to INIT_TASK_DONE. When this is called, the
+ // state should be INIT_TASK_SCHEDULED.
+ void FinishedGatheringInitialMetrics();
+
+ void OnUserAction(const std::string& action);
+
+ // Get the amount of uptime since this process started and since the last
+ // call to this function. Also updates the cumulative uptime metric (stored
+ // as a pref) for uninstall. Uptimes are measured using TimeTicks, which
+ // guarantees that it is monotonic and does not jump if the user changes
+ // his/her clock. The TimeTicks implementation also makes the clock not
+ // count time the computer is suspended.
+ void GetUptimes(PrefService* pref,
+ base::TimeDelta* incremental_uptime,
+ base::TimeDelta* uptime);
+
+ // Turns recording on or off.
+ // DisableRecording() also forces a persistent save of logging state (if
+ // anything has been recorded, or transmitted).
+ void EnableRecording();
+ void DisableRecording();
+
+ // If in_idle is true, sets idle_since_last_transmission to true.
+ // If in_idle is false and idle_since_last_transmission_ is true, sets
+ // idle_since_last_transmission to false and starts the timer (provided
+ // starting the timer is permitted).
+ void HandleIdleSinceLastTransmission(bool in_idle);
+
+ // Set up client ID, session ID, etc.
+ void InitializeMetricsState();
+
+ // Registers/unregisters |observer| to receive MetricsLog notifications.
+ void AddObserver(MetricsServiceObserver* observer);
+ void RemoveObserver(MetricsServiceObserver* observer);
+ void NotifyOnDidCreateMetricsLog();
+
+ // Schedule the next save of LocalState information. This is called
+ // automatically by the task that performs each save to schedule the next one.
+ void ScheduleNextStateSave();
+
+ // Save the LocalState information immediately. This should not be called by
+ // anybody other than the scheduler to avoid doing too many writes. When you
+ // make a change, call ScheduleNextStateSave() instead.
+ void SaveLocalState();
+
+ // Opens a new log for recording user experience metrics.
+ void OpenNewLog();
+
+ // Closes out the current log after adding any last information.
+ void CloseCurrentLog();
+
+ // Pushes the text of the current and staged logs into persistent storage.
+ // Called when Chrome shuts down.
+ void PushPendingLogsToPersistentStorage();
+
+ // Ensures that scheduler is running, assuming the current settings are such
+ // that metrics should be reported. If not, this is a no-op.
+ void StartSchedulerIfNecessary();
+
+ // Starts the process of uploading metrics data.
+ void StartScheduledUpload();
+
+ // Called by the client when final log info collection is complete.
+ void OnFinalLogInfoCollectionDone();
+
+ // Either closes the current log or creates and closes the initial log
+ // (depending on |state_|), and stages it for upload.
+ void StageNewLog();
+
+ // Prepares the initial stability log, which is only logged when the previous
+ // run of Chrome crashed. This log contains any stability metrics left over
+ // from that previous run, and only these stability metrics. It uses the
+ // system profile from the previous session.
+ void PrepareInitialStabilityLog();
+
+ // Prepares the initial metrics log, which includes startup histograms and
+ // profiler data, as well as incremental stability-related metrics.
+ void PrepareInitialMetricsLog();
+
+ // Uploads the currently staged log (which must be non-null).
+ void SendStagedLog();
+
+ // Called after transmission completes (either successfully or with failure).
+ void OnLogUploadComplete(int response_code);
+
+ // Reads, increments and then sets the specified integer preference.
+ void IncrementPrefValue(const char* path);
+
+ // Reads, increments and then sets the specified long preference that is
+ // stored as a string.
+ void IncrementLongPrefsValue(const char* path);
+
+ // Records that the browser was shut down cleanly.
+ void LogCleanShutdown();
+
+ // Records state that should be periodically saved, like uptime and
+ // buffered plugin stability statistics.
+ void RecordCurrentState(PrefService* pref);
+
+ // Checks whether events should currently be logged.
+ bool ShouldLogEvents();
+
+ // Sets the value of the specified path in prefs and schedules a save.
+ void RecordBooleanPrefValue(const char* path, bool value);
+
+ // Returns a list of synthetic field trials that were active for the entire
+ // duration of the current log.
+ void GetCurrentSyntheticFieldTrials(
+ std::vector<variations::ActiveGroupId>* synthetic_trials);
+
+ // Creates a new MetricsLog instance with the given |log_type|.
+ scoped_ptr<MetricsLog> CreateLog(MetricsLog::LogType log_type);
+
+ // Record complete list of histograms into the current log.
+ // Called when we close a log.
+ void RecordCurrentHistograms();
+
+ // Record complete list of stability histograms into the current log,
+ // i.e., histograms with the |kUmaStabilityHistogramFlag| flag set.
+ void RecordCurrentStabilityHistograms();
+
+ // Manager for the various in-flight logs.
+ metrics::MetricsLogManager log_manager_;
+
+ // |histogram_snapshot_manager_| prepares histogram deltas for transmission.
+ base::HistogramSnapshotManager histogram_snapshot_manager_;
+
+ // Used to manage various metrics reporting state prefs, such as client id,
+ // low entropy source and whether metrics reporting is enabled. Weak pointer.
+ metrics::MetricsStateManager* const state_manager_;
+
+ // Used to interact with the embedder. Weak pointer; must outlive |this|
+ // instance.
+ metrics::MetricsServiceClient* const client_;
+
+ // Registered metrics providers.
+ ScopedVector<metrics::MetricsProvider> metrics_providers_;
+
+ PrefService* local_state_;
+
+ base::ActionCallback action_callback_;
+
+ // Indicate whether recording and reporting are currently happening.
+ // These should not be set directly, but by calling SetRecording and
+ // SetReporting.
+ bool recording_active_;
+ bool reporting_active_;
+
+ // Indicate whether test mode is enabled, where the initial log should never
+ // be cut, and logs are neither persisted nor uploaded.
+ bool test_mode_active_;
+
+ // The progression of states made by the browser are recorded in the following
+ // state.
+ State state_;
+
+ // Whether the initial stability log has been recorded during startup.
+ bool has_initial_stability_log_;
+
+ // The initial metrics log, used to record startup metrics (histograms and
+ // profiler data). Note that if a crash occurred in the previous session, an
+ // initial stability log may be sent before this.
+ scoped_ptr<MetricsLog> initial_metrics_log_;
+
+ // Instance of the helper class for uploading logs.
+ scoped_ptr<metrics::MetricsLogUploader> log_uploader_;
+
+ // Whether there is a current log upload in progress.
+ bool log_upload_in_progress_;
+
+ // Whether the MetricsService object has received any notifications since
+ // the last time a transmission was sent.
+ bool idle_since_last_transmission_;
+
+ // A number that identifies the how many times the app has been launched.
+ int session_id_;
+
+ // Weak pointers factory used to post task on different threads. All weak
+ // pointers managed by this factory have the same lifetime as MetricsService.
+ base::WeakPtrFactory<MetricsService> self_ptr_factory_;
+
+ // Weak pointers factory used for saving state. All weak pointers managed by
+ // this factory are invalidated in ScheduleNextStateSave.
+ base::WeakPtrFactory<MetricsService> state_saver_factory_;
+
+ // The scheduler for determining when uploads should happen.
+ scoped_ptr<MetricsReportingScheduler> scheduler_;
+
+ // Stores the time of the first call to |GetUptimes()|.
+ base::TimeTicks first_updated_time_;
+
+ // Stores the time of the last call to |GetUptimes()|.
+ base::TimeTicks last_updated_time_;
+
+ // Execution phase the browser is in.
+ static ExecutionPhase execution_phase_;
+
+ // Reduntant marker to check that we completed our shutdown, and set the
+ // exited-cleanly bit in the prefs.
+ static ShutdownCleanliness clean_shutdown_status_;
+
+ // Field trial groups that map to Chrome configuration states.
+ SyntheticTrialGroups synthetic_trial_groups_;
+
+ ObserverList<MetricsServiceObserver> observers_;
+
+ // Confirms single-threaded access to |observers_| in debug builds.
+ base::ThreadChecker thread_checker_;
+
+ friend class MetricsServiceAccessor;
+
+ FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, IsPluginProcess);
+ FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, MetricsServiceObserver);
+ FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest,
+ PermutedEntropyCacheClearedWhenLowEntropyReset);
+ FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, RegisterSyntheticTrial);
+
+ DISALLOW_COPY_AND_ASSIGN(MetricsService);
+};
+
+#endif // COMPONENTS_METRICS_METRICS_SERVICE_H_