• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
log_manager()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