Home | History | Annotate | Download | only in metrics
      1 // Copyright 2014 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.
      4 
      5 // This file defines a service that collects information about the user
      6 // experience in order to help improve future versions of the app.
      7 
      8 #ifndef COMPONENTS_METRICS_METRICS_SERVICE_H_
      9 #define COMPONENTS_METRICS_METRICS_SERVICE_H_
     10 
     11 #include <map>
     12 #include <string>
     13 #include <vector>
     14 
     15 #include "base/basictypes.h"
     16 #include "base/gtest_prod_util.h"
     17 #include "base/memory/scoped_ptr.h"
     18 #include "base/memory/scoped_vector.h"
     19 #include "base/memory/weak_ptr.h"
     20 #include "base/metrics/field_trial.h"
     21 #include "base/metrics/histogram_flattener.h"
     22 #include "base/metrics/histogram_snapshot_manager.h"
     23 #include "base/metrics/user_metrics.h"
     24 #include "base/observer_list.h"
     25 #include "base/strings/string16.h"
     26 #include "base/threading/thread_checker.h"
     27 #include "base/time/time.h"
     28 #include "components/metrics/metrics_log.h"
     29 #include "components/metrics/metrics_log_manager.h"
     30 #include "components/metrics/metrics_provider.h"
     31 #include "components/metrics/metrics_service_observer.h"
     32 #include "components/variations/active_field_trials.h"
     33 
     34 class MetricsReportingScheduler;
     35 class PrefService;
     36 class PrefRegistrySimple;
     37 
     38 namespace base {
     39 class DictionaryValue;
     40 class HistogramSamples;
     41 class MessageLoopProxy;
     42 class PrefService;
     43 }
     44 
     45 namespace variations {
     46 struct ActiveGroupId;
     47 }
     48 
     49 namespace metrics {
     50 class MetricsLogUploader;
     51 class MetricsServiceClient;
     52 class MetricsStateManager;
     53 }
     54 
     55 namespace net {
     56 class URLFetcher;
     57 }
     58 
     59 // A Field Trial and its selected group, which represent a particular
     60 // Chrome configuration state. For example, the trial name could map to
     61 // a preference name, and the group name could map to a preference value.
     62 struct SyntheticTrialGroup {
     63  public:
     64   ~SyntheticTrialGroup();
     65 
     66   variations::ActiveGroupId id;
     67   base::TimeTicks start_time;
     68 
     69  private:
     70   friend class MetricsService;
     71   FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, RegisterSyntheticTrial);
     72 
     73   // This constructor is private specifically so as to control which code is
     74   // able to access it. New code that wishes to use it should be added as a
     75   // friend class.
     76   SyntheticTrialGroup(uint32 trial, uint32 group);
     77 };
     78 
     79 class MetricsService : public base::HistogramFlattener {
     80  public:
     81   // The execution phase of the browser.
     82   enum ExecutionPhase {
     83     UNINITIALIZED_PHASE = 0,
     84     START_METRICS_RECORDING = 100,
     85     CREATE_PROFILE = 200,
     86     STARTUP_TIMEBOMB_ARM = 300,
     87     THREAD_WATCHER_START = 400,
     88     MAIN_MESSAGE_LOOP_RUN = 500,
     89     SHUTDOWN_TIMEBOMB_ARM = 600,
     90     SHUTDOWN_COMPLETE = 700,
     91   };
     92 
     93   // Creates the MetricsService with the given |state_manager|, |client|, and
     94   // |local_state|.  Does not take ownership of the paramaters; instead stores
     95   // a weak pointer to each. Caller should ensure that the parameters are valid
     96   // for the lifetime of this class.
     97   MetricsService(metrics::MetricsStateManager* state_manager,
     98                  metrics::MetricsServiceClient* client,
     99                  PrefService* local_state);
    100   virtual ~MetricsService();
    101 
    102   // Initializes metrics recording state. Updates various bookkeeping values in
    103   // prefs and sets up the scheduler. This is a separate function rather than
    104   // being done by the constructor so that field trials could be created before
    105   // this is run.
    106   void InitializeMetricsRecordingState();
    107 
    108   // Starts the metrics system, turning on recording and uploading of metrics.
    109   // Should be called when starting up with metrics enabled, or when metrics
    110   // are turned on.
    111   void Start();
    112 
    113   // If metrics reporting is enabled, starts the metrics service. Returns
    114   // whether the metrics service was started.
    115   bool StartIfMetricsReportingEnabled();
    116 
    117   // Starts the metrics system in a special test-only mode. Metrics won't ever
    118   // be uploaded or persisted in this mode, but metrics will be recorded in
    119   // memory.
    120   void StartRecordingForTests();
    121 
    122   // Shuts down the metrics system. Should be called at shutdown, or if metrics
    123   // are turned off.
    124   void Stop();
    125 
    126   // Enable/disable transmission of accumulated logs and crash reports (dumps).
    127   // Calling Start() automatically enables reporting, but sending is
    128   // asyncronous so this can be called immediately after Start() to prevent
    129   // any uploading.
    130   void EnableReporting();
    131   void DisableReporting();
    132 
    133   // Returns the client ID for this client, or the empty string if metrics
    134   // recording is not currently running.
    135   std::string GetClientId();
    136 
    137   // Returns the preferred entropy provider used to seed persistent activities
    138   // based on whether or not metrics reporting will be permitted on this client.
    139   //
    140   // If metrics reporting is enabled, this method returns an entropy provider
    141   // that has a high source of entropy, partially based on the client ID.
    142   // Otherwise, it returns an entropy provider that is based on a low entropy
    143   // source.
    144   scoped_ptr<const base::FieldTrial::EntropyProvider> CreateEntropyProvider();
    145 
    146   // At startup, prefs needs to be called with a list of all the pref names and
    147   // types we'll be using.
    148   static void RegisterPrefs(PrefRegistrySimple* registry);
    149 
    150   // HistogramFlattener:
    151   virtual void RecordDelta(const base::HistogramBase& histogram,
    152                            const base::HistogramSamples& snapshot) OVERRIDE;
    153   virtual void InconsistencyDetected(
    154       base::HistogramBase::Inconsistency problem) OVERRIDE;
    155   virtual void UniqueInconsistencyDetected(
    156       base::HistogramBase::Inconsistency problem) OVERRIDE;
    157   virtual void InconsistencyDetectedInLoggedCount(int amount) OVERRIDE;
    158 
    159   // This should be called when the application is not idle, i.e. the user seems
    160   // to be interacting with the application.
    161   void OnApplicationNotIdle();
    162 
    163   // Invoked when we get a WM_SESSIONEND. This places a value in prefs that is
    164   // reset when RecordCompletedSessionEnd is invoked.
    165   void RecordStartOfSessionEnd();
    166 
    167   // This should be called when the application is shutting down. It records
    168   // that session end was successful.
    169   void RecordCompletedSessionEnd();
    170 
    171 #if defined(OS_ANDROID) || defined(OS_IOS)
    172   // Called when the application is going into background mode.
    173   void OnAppEnterBackground();
    174 
    175   // Called when the application is coming out of background mode.
    176   void OnAppEnterForeground();
    177 #else
    178   // Set the dirty flag, which will require a later call to LogCleanShutdown().
    179   static void LogNeedForCleanShutdown(PrefService* local_state);
    180 #endif  // defined(OS_ANDROID) || defined(OS_IOS)
    181 
    182   static void SetExecutionPhase(ExecutionPhase execution_phase,
    183                                 PrefService* local_state);
    184 
    185   // Saves in the preferences if the crash report registration was successful.
    186   // This count is eventually send via UMA logs.
    187   void RecordBreakpadRegistration(bool success);
    188 
    189   // Saves in the preferences if the browser is running under a debugger.
    190   // This count is eventually send via UMA logs.
    191   void RecordBreakpadHasDebugger(bool has_debugger);
    192 
    193   bool recording_active() const;
    194   bool reporting_active() const;
    195 
    196   // Redundant test to ensure that we are notified of a clean exit.
    197   // This value should be true when process has completed shutdown.
    198   static bool UmaMetricsProperlyShutdown();
    199 
    200   // Registers a field trial name and group to be used to annotate a UMA report
    201   // with a particular Chrome configuration state. A UMA report will be
    202   // annotated with this trial group if and only if all events in the report
    203   // were created after the trial is registered. Only one group name may be
    204   // registered at a time for a given trial_name. Only the last group name that
    205   // is registered for a given trial name will be recorded. The values passed
    206   // in must not correspond to any real field trial in the code.
    207   // To use this method, SyntheticTrialGroup should friend your class.
    208   void RegisterSyntheticFieldTrial(const SyntheticTrialGroup& trial_group);
    209 
    210   // Register the specified |provider| to provide additional metrics into the
    211   // UMA log. Should be called during MetricsService initialization only.
    212   void RegisterMetricsProvider(scoped_ptr<metrics::MetricsProvider> provider);
    213 
    214   // Check if this install was cloned or imaged from another machine. If a
    215   // clone is detected, reset the client id and low entropy source. This
    216   // should not be called more than once.
    217   void CheckForClonedInstall(
    218       scoped_refptr<base::SingleThreadTaskRunner> task_runner);
    219 
    220  protected:
    221   // Exposed for testing.
    222   metrics::MetricsLogManager* log_manager() { return &log_manager_; }
    223 
    224  private:
    225   // The MetricsService has a lifecycle that is stored as a state.
    226   // See metrics_service.cc for description of this lifecycle.
    227   enum State {
    228     INITIALIZED,                    // Constructor was called.
    229     INIT_TASK_SCHEDULED,            // Waiting for deferred init tasks to
    230                                     // complete.
    231     INIT_TASK_DONE,                 // Waiting for timer to send initial log.
    232     SENDING_INITIAL_STABILITY_LOG,  // Initial stability log being sent.
    233     SENDING_INITIAL_METRICS_LOG,    // Initial metrics log being sent.
    234     SENDING_OLD_LOGS,               // Sending unsent logs from last session.
    235     SENDING_CURRENT_LOGS,           // Sending ongoing logs as they accrue.
    236   };
    237 
    238   enum ShutdownCleanliness {
    239     CLEANLY_SHUTDOWN = 0xdeadbeef,
    240     NEED_TO_SHUTDOWN = ~CLEANLY_SHUTDOWN
    241   };
    242 
    243   typedef std::vector<SyntheticTrialGroup> SyntheticTrialGroups;
    244 
    245   // Calls into the client to start metrics gathering.
    246   void StartGatheringMetrics();
    247 
    248   // Callback that moves the state to INIT_TASK_DONE. When this is called, the
    249   // state should be INIT_TASK_SCHEDULED.
    250   void FinishedGatheringInitialMetrics();
    251 
    252   void OnUserAction(const std::string& action);
    253 
    254   // Get the amount of uptime since this process started and since the last
    255   // call to this function.  Also updates the cumulative uptime metric (stored
    256   // as a pref) for uninstall.  Uptimes are measured using TimeTicks, which
    257   // guarantees that it is monotonic and does not jump if the user changes
    258   // his/her clock.  The TimeTicks implementation also makes the clock not
    259   // count time the computer is suspended.
    260   void GetUptimes(PrefService* pref,
    261                   base::TimeDelta* incremental_uptime,
    262                   base::TimeDelta* uptime);
    263 
    264   // Turns recording on or off.
    265   // DisableRecording() also forces a persistent save of logging state (if
    266   // anything has been recorded, or transmitted).
    267   void EnableRecording();
    268   void DisableRecording();
    269 
    270   // If in_idle is true, sets idle_since_last_transmission to true.
    271   // If in_idle is false and idle_since_last_transmission_ is true, sets
    272   // idle_since_last_transmission to false and starts the timer (provided
    273   // starting the timer is permitted).
    274   void HandleIdleSinceLastTransmission(bool in_idle);
    275 
    276   // Set up client ID, session ID, etc.
    277   void InitializeMetricsState();
    278 
    279   // Registers/unregisters |observer| to receive MetricsLog notifications.
    280   void AddObserver(MetricsServiceObserver* observer);
    281   void RemoveObserver(MetricsServiceObserver* observer);
    282   void NotifyOnDidCreateMetricsLog();
    283 
    284   // Schedule the next save of LocalState information.  This is called
    285   // automatically by the task that performs each save to schedule the next one.
    286   void ScheduleNextStateSave();
    287 
    288   // Save the LocalState information immediately. This should not be called by
    289   // anybody other than the scheduler to avoid doing too many writes. When you
    290   // make a change, call ScheduleNextStateSave() instead.
    291   void SaveLocalState();
    292 
    293   // Opens a new log for recording user experience metrics.
    294   void OpenNewLog();
    295 
    296   // Closes out the current log after adding any last information.
    297   void CloseCurrentLog();
    298 
    299   // Pushes the text of the current and staged logs into persistent storage.
    300   // Called when Chrome shuts down.
    301   void PushPendingLogsToPersistentStorage();
    302 
    303   // Ensures that scheduler is running, assuming the current settings are such
    304   // that metrics should be reported. If not, this is a no-op.
    305   void StartSchedulerIfNecessary();
    306 
    307   // Starts the process of uploading metrics data.
    308   void StartScheduledUpload();
    309 
    310   // Called by the client when final log info collection is complete.
    311   void OnFinalLogInfoCollectionDone();
    312 
    313   // Either closes the current log or creates and closes the initial log
    314   // (depending on |state_|), and stages it for upload.
    315   void StageNewLog();
    316 
    317   // Prepares the initial stability log, which is only logged when the previous
    318   // run of Chrome crashed.  This log contains any stability metrics left over
    319   // from that previous run, and only these stability metrics.  It uses the
    320   // system profile from the previous session.
    321   void PrepareInitialStabilityLog();
    322 
    323   // Prepares the initial metrics log, which includes startup histograms and
    324   // profiler data, as well as incremental stability-related metrics.
    325   void PrepareInitialMetricsLog();
    326 
    327   // Uploads the currently staged log (which must be non-null).
    328   void SendStagedLog();
    329 
    330   // Called after transmission completes (either successfully or with failure).
    331   void OnLogUploadComplete(int response_code);
    332 
    333   // Reads, increments and then sets the specified integer preference.
    334   void IncrementPrefValue(const char* path);
    335 
    336   // Reads, increments and then sets the specified long preference that is
    337   // stored as a string.
    338   void IncrementLongPrefsValue(const char* path);
    339 
    340   // Records that the browser was shut down cleanly.
    341   void LogCleanShutdown();
    342 
    343   // Records state that should be periodically saved, like uptime and
    344   // buffered plugin stability statistics.
    345   void RecordCurrentState(PrefService* pref);
    346 
    347   // Checks whether events should currently be logged.
    348   bool ShouldLogEvents();
    349 
    350   // Sets the value of the specified path in prefs and schedules a save.
    351   void RecordBooleanPrefValue(const char* path, bool value);
    352 
    353   // Returns a list of synthetic field trials that were active for the entire
    354   // duration of the current log.
    355   void GetCurrentSyntheticFieldTrials(
    356       std::vector<variations::ActiveGroupId>* synthetic_trials);
    357 
    358   // Creates a new MetricsLog instance with the given |log_type|.
    359   scoped_ptr<MetricsLog> CreateLog(MetricsLog::LogType log_type);
    360 
    361   // Record complete list of histograms into the current log.
    362   // Called when we close a log.
    363   void RecordCurrentHistograms();
    364 
    365   // Record complete list of stability histograms into the current log,
    366   // i.e., histograms with the |kUmaStabilityHistogramFlag| flag set.
    367   void RecordCurrentStabilityHistograms();
    368 
    369   // Manager for the various in-flight logs.
    370   metrics::MetricsLogManager log_manager_;
    371 
    372   // |histogram_snapshot_manager_| prepares histogram deltas for transmission.
    373   base::HistogramSnapshotManager histogram_snapshot_manager_;
    374 
    375   // Used to manage various metrics reporting state prefs, such as client id,
    376   // low entropy source and whether metrics reporting is enabled. Weak pointer.
    377   metrics::MetricsStateManager* const state_manager_;
    378 
    379   // Used to interact with the embedder. Weak pointer; must outlive |this|
    380   // instance.
    381   metrics::MetricsServiceClient* const client_;
    382 
    383   // Registered metrics providers.
    384   ScopedVector<metrics::MetricsProvider> metrics_providers_;
    385 
    386   PrefService* local_state_;
    387 
    388   base::ActionCallback action_callback_;
    389 
    390   // Indicate whether recording and reporting are currently happening.
    391   // These should not be set directly, but by calling SetRecording and
    392   // SetReporting.
    393   bool recording_active_;
    394   bool reporting_active_;
    395 
    396   // Indicate whether test mode is enabled, where the initial log should never
    397   // be cut, and logs are neither persisted nor uploaded.
    398   bool test_mode_active_;
    399 
    400   // The progression of states made by the browser are recorded in the following
    401   // state.
    402   State state_;
    403 
    404   // Whether the initial stability log has been recorded during startup.
    405   bool has_initial_stability_log_;
    406 
    407   // The initial metrics log, used to record startup metrics (histograms and
    408   // profiler data). Note that if a crash occurred in the previous session, an
    409   // initial stability log may be sent before this.
    410   scoped_ptr<MetricsLog> initial_metrics_log_;
    411 
    412   // Instance of the helper class for uploading logs.
    413   scoped_ptr<metrics::MetricsLogUploader> log_uploader_;
    414 
    415   // Whether there is a current log upload in progress.
    416   bool log_upload_in_progress_;
    417 
    418   // Whether the MetricsService object has received any notifications since
    419   // the last time a transmission was sent.
    420   bool idle_since_last_transmission_;
    421 
    422   // A number that identifies the how many times the app has been launched.
    423   int session_id_;
    424 
    425   // Weak pointers factory used to post task on different threads. All weak
    426   // pointers managed by this factory have the same lifetime as MetricsService.
    427   base::WeakPtrFactory<MetricsService> self_ptr_factory_;
    428 
    429   // Weak pointers factory used for saving state. All weak pointers managed by
    430   // this factory are invalidated in ScheduleNextStateSave.
    431   base::WeakPtrFactory<MetricsService> state_saver_factory_;
    432 
    433   // The scheduler for determining when uploads should happen.
    434   scoped_ptr<MetricsReportingScheduler> scheduler_;
    435 
    436   // Stores the time of the first call to |GetUptimes()|.
    437   base::TimeTicks first_updated_time_;
    438 
    439   // Stores the time of the last call to |GetUptimes()|.
    440   base::TimeTicks last_updated_time_;
    441 
    442   // Execution phase the browser is in.
    443   static ExecutionPhase execution_phase_;
    444 
    445   // Reduntant marker to check that we completed our shutdown, and set the
    446   // exited-cleanly bit in the prefs.
    447   static ShutdownCleanliness clean_shutdown_status_;
    448 
    449   // Field trial groups that map to Chrome configuration states.
    450   SyntheticTrialGroups synthetic_trial_groups_;
    451 
    452   ObserverList<MetricsServiceObserver> observers_;
    453 
    454   // Confirms single-threaded access to |observers_| in debug builds.
    455   base::ThreadChecker thread_checker_;
    456 
    457   friend class MetricsServiceAccessor;
    458 
    459   FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, IsPluginProcess);
    460   FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, MetricsServiceObserver);
    461   FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest,
    462                            PermutedEntropyCacheClearedWhenLowEntropyReset);
    463   FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, RegisterSyntheticTrial);
    464 
    465   DISALLOW_COPY_AND_ASSIGN(MetricsService);
    466 };
    467 
    468 #endif  // COMPONENTS_METRICS_METRICS_SERVICE_H_
    469