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