1 // Copyright (c) 2012 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.
5 // This file defines a service that collects information about the user
6 // experience in order to help improve future versions of the app.
8 #ifndef CHROME_BROWSER_METRICS_METRICS_SERVICE_H_
9 #define CHROME_BROWSER_METRICS_METRICS_SERVICE_H_
15 #include "base/basictypes.h"
16 #include "base/gtest_prod_util.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/memory/weak_ptr.h"
19 #include "base/metrics/field_trial.h"
20 #include "base/metrics/user_metrics.h"
21 #include "base/process/kill.h"
22 #include "base/time/time.h"
23 #include "chrome/browser/metrics/metrics_log.h"
24 #include "chrome/browser/metrics/tracking_synchronizer_observer.h"
25 #include "chrome/common/metrics/metrics_service_base.h"
26 #include "chrome/installer/util/google_update_settings.h"
27 #include "content/public/browser/browser_child_process_observer.h"
28 #include "content/public/browser/notification_observer.h"
29 #include "content/public/browser/notification_registrar.h"
30 #include "content/public/browser/user_metrics.h"
31 #include "net/url_request/url_fetcher_delegate.h"
33 #if defined(OS_ANDROID)
34 #include "chrome/browser/android/activity_type_ids.h"
35 #elif defined(OS_CHROMEOS)
36 #include "chrome/browser/chromeos/external_metrics.h"
39 class MetricsReportingScheduler;
41 class PrefRegistrySimple;
43 class TemplateURLService;
46 class DictionaryValue;
47 class MessageLoopProxy;
50 namespace chrome_variations {
55 class RenderProcessHost;
60 namespace extensions {
61 class ExtensionDownloader;
62 class ManifestFetchData;
70 bool IsOmniboxEnabled(Profile* profile);
73 namespace tracked_objects {
74 struct ProcessDataSnapshot;
77 // A Field Trial and its selected group, which represent a particular
78 // Chrome configuration state. For example, the trial name could map to
79 // a preference name, and the group name could map to a preference value.
80 struct SyntheticTrialGroup {
82 ~SyntheticTrialGroup();
84 chrome_variations::ActiveGroupId id;
85 base::TimeTicks start_time;
88 friend class MetricsService;
89 FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, RegisterSyntheticTrial);
91 // This constructor is private specifically so as to control which code is
92 // able to access it. New code that wishes to use it should be added as a
94 SyntheticTrialGroup(uint32 trial, uint32 group, base::TimeTicks start);
99 : public chrome_browser_metrics::TrackingSynchronizerObserver,
100 public content::BrowserChildProcessObserver,
101 public content::NotificationObserver,
102 public net::URLFetcherDelegate,
103 public MetricsServiceBase {
105 // The execution phase of the browser.
106 enum ExecutionPhase {
107 UNINITIALIZED_PHASE = 0,
108 START_METRICS_RECORDING = 100,
109 CREATE_PROFILE = 200,
110 STARTUP_TIMEBOMB_ARM = 300,
111 THREAD_WATCHER_START = 400,
112 MAIN_MESSAGE_LOOP_RUN = 500,
113 SHUTDOWN_TIMEBOMB_ARM = 600,
114 SHUTDOWN_COMPLETE = 700,
117 enum ReportingState {
123 virtual ~MetricsService();
125 // Initializes metrics recording state. Updates various bookkeeping values in
126 // prefs and sets up the scheduler. This is a separate function rather than
127 // being done by the constructor so that field trials could be created before
128 // this is run. Takes |reporting_state| parameter which specifies whether UMA
130 void InitializeMetricsRecordingState(ReportingState reporting_state);
132 // Starts the metrics system, turning on recording and uploading of metrics.
133 // Should be called when starting up with metrics enabled, or when metrics
137 // Starts the metrics system in a special test-only mode. Metrics won't ever
138 // be uploaded or persisted in this mode, but metrics will be recorded in
140 void StartRecordingForTests();
142 // Shuts down the metrics system. Should be called at shutdown, or if metrics
146 // Enable/disable transmission of accumulated logs and crash reports (dumps).
147 // Calling Start() automatically enables reporting, but sending is
148 // asyncronous so this can be called immediately after Start() to prevent
150 void EnableReporting();
151 void DisableReporting();
153 // Returns the client ID for this client, or the empty string if metrics
154 // recording is not currently running.
155 std::string GetClientId();
157 // Returns the preferred entropy provider used to seed persistent activities
158 // based on whether or not metrics reporting will be permitted on this client.
159 // The caller must determine if metrics reporting will be enabled for this
160 // client and pass that state in as |reporting_will_be_enabled|.
162 // If |reporting_will_be_enabled| is true, this method returns an entropy
163 // provider that has a high source of entropy, partially based on the client
164 // ID. Otherwise, an entropy provider that is based on a low entropy source
167 // Note that this reporting state can not be checked by reporting_active()
168 // because this method may need to be called before the MetricsService needs
170 scoped_ptr<const base::FieldTrial::EntropyProvider> CreateEntropyProvider(
171 ReportingState reporting_state);
173 // Force the client ID to be generated. This is useful in case it's needed
175 void ForceClientIdCreation();
177 // At startup, prefs needs to be called with a list of all the pref names and
178 // types we'll be using.
179 static void RegisterPrefs(PrefRegistrySimple* registry);
180 #if defined(OS_ANDROID)
181 static void RegisterPrefsAndroid(PrefRegistrySimple* registry);
182 #endif // defined(OS_ANDROID)
184 // Set up notifications which indicate that a user is performing work. This is
185 // useful to allow some features to sleep, until the machine becomes active,
186 // such as precluding UMA uploads unless there was recent activity.
187 static void SetUpNotifications(content::NotificationRegistrar* registrar,
188 content::NotificationObserver* observer);
190 // Implementation of content::BrowserChildProcessObserver
191 virtual void BrowserChildProcessHostConnected(
192 const content::ChildProcessData& data) OVERRIDE;
193 virtual void BrowserChildProcessCrashed(
194 const content::ChildProcessData& data) OVERRIDE;
195 virtual void BrowserChildProcessInstanceCreated(
196 const content::ChildProcessData& data) OVERRIDE;
198 // Implementation of content::NotificationObserver
199 virtual void Observe(int type,
200 const content::NotificationSource& source,
201 const content::NotificationDetails& details) OVERRIDE;
203 // Invoked when we get a WM_SESSIONEND. This places a value in prefs that is
204 // reset when RecordCompletedSessionEnd is invoked.
205 void RecordStartOfSessionEnd();
207 // This should be called when the application is shutting down. It records
208 // that session end was successful.
209 void RecordCompletedSessionEnd();
211 #if defined(OS_ANDROID)
212 // Called to log launch and crash stats to preferences.
213 void LogAndroidStabilityToPrefs(PrefService* pref);
215 // Converts crash stats stored in the preferences into histograms.
216 void ConvertAndroidStabilityPrefsToHistograms(PrefService* pref);
218 // Called when the Activity that the user interacts with is swapped out.
219 void OnForegroundActivityChanged(PrefService* pref,
220 ActivityTypeIds::Type type);
221 #endif // defined(OS_ANDROID)
223 #if defined(OS_ANDROID) || defined(OS_IOS)
224 // Called when the application is going into background mode.
225 void OnAppEnterBackground();
227 // Called when the application is coming out of background mode.
228 void OnAppEnterForeground();
230 // Set the dirty flag, which will require a later call to LogCleanShutdown().
231 static void LogNeedForCleanShutdown();
232 #endif // defined(OS_ANDROID) || defined(OS_IOS)
234 static void SetExecutionPhase(ExecutionPhase execution_phase);
236 // Saves in the preferences if the crash report registration was successful.
237 // This count is eventually send via UMA logs.
238 void RecordBreakpadRegistration(bool success);
240 // Saves in the preferences if the browser is running under a debugger.
241 // This count is eventually send via UMA logs.
242 void RecordBreakpadHasDebugger(bool has_debugger);
245 // Counts (and removes) the browser crash dump attempt signals left behind by
246 // any previous browser processes which generated a crash dump.
247 void CountBrowserCrashDumpAttempts();
250 #if defined(OS_CHROMEOS)
251 // Start the external metrics service, which collects metrics from Chrome OS
252 // and passes them to UMA.
253 void StartExternalMetrics();
255 // Records a Chrome OS crash.
256 void LogChromeOSCrash(const std::string &crash_type);
259 bool recording_active() const;
260 bool reporting_active() const;
262 void LogPluginLoadingError(const base::FilePath& plugin_path);
264 // Redundant test to ensure that we are notified of a clean exit.
265 // This value should be true when process has completed shutdown.
266 static bool UmaMetricsProperlyShutdown();
268 // Registers a field trial name and group to be used to annotate a UMA report
269 // with a particular Chrome configuration state. A UMA report will be
270 // annotated with this trial group if and only if all events in the report
271 // were created after the trial is registered. Only one group name may be
272 // registered at a time for a given trial_name. Only the last group name that
273 // is registered for a given trial name will be recorded. The values passed
274 // in must not correspond to any real field trial in the code.
275 // To use this method, SyntheticTrialGroup should friend your class.
276 void RegisterSyntheticFieldTrial(const SyntheticTrialGroup& trial_group);
279 // The MetricsService has a lifecycle that is stored as a state.
280 // See metrics_service.cc for description of this lifecycle.
282 INITIALIZED, // Constructor was called.
283 INIT_TASK_SCHEDULED, // Waiting for deferred init tasks to
285 INIT_TASK_DONE, // Waiting for timer to send initial log.
286 SENDING_INITIAL_STABILITY_LOG, // Initial stability log being sent.
287 SENDING_INITIAL_METRICS_LOG, // Initial metrics log being sent.
288 SENDING_OLD_LOGS, // Sending unsent logs from last session.
289 SENDING_CURRENT_LOGS, // Sending ongoing logs as they accrue.
292 enum ShutdownCleanliness {
293 CLEANLY_SHUTDOWN = 0xdeadbeef,
294 NEED_TO_SHUTDOWN = ~CLEANLY_SHUTDOWN
297 // Designates which entropy source was returned from this MetricsService.
298 // This is used for testing to validate that we return the correct source
299 // depending on the state of the service.
300 enum EntropySourceReturned {
306 struct ChildProcessStats;
308 typedef std::vector<SyntheticTrialGroup> SyntheticTrialGroups;
310 // First part of the init task. Called on the FILE thread to load hardware
311 // class information.
312 static void InitTaskGetHardwareClass(base::WeakPtr<MetricsService> self,
313 base::MessageLoopProxy* target_loop);
315 // Callback from InitTaskGetHardwareClass() that continues the init task by
316 // loading plugin information.
317 void OnInitTaskGotHardwareClass(const std::string& hardware_class);
319 // Callback from PluginService::GetPlugins() that continues the init task by
320 // launching a task to gather Google Update statistics.
321 void OnInitTaskGotPluginInfo(
322 const std::vector<content::WebPluginInfo>& plugins);
324 // Task launched by OnInitTaskGotPluginInfo() that continues the init task by
325 // loading Google Update statistics. Called on a blocking pool thread.
326 static void InitTaskGetGoogleUpdateData(base::WeakPtr<MetricsService> self,
327 base::MessageLoopProxy* target_loop);
329 // Callback from InitTaskGetGoogleUpdateData() that continues the init task by
330 // loading profiler data.
331 void OnInitTaskGotGoogleUpdateData(
332 const GoogleUpdateMetrics& google_update_metrics);
334 void OnUserAction(const std::string& action);
336 // TrackingSynchronizerObserver:
337 virtual void ReceivedProfilerData(
338 const tracked_objects::ProcessDataSnapshot& process_data,
339 int process_type) OVERRIDE;
340 // Callback that moves the state to INIT_TASK_DONE.
341 virtual void FinishedReceivingProfilerData() OVERRIDE;
343 // Get the amount of uptime since this function was last called.
344 // This updates the cumulative uptime metric for uninstall as a side effect.
345 base::TimeDelta GetIncrementalUptime(PrefService* pref);
347 // Returns the low entropy source for this client. This is a random value
348 // that is non-identifying amongst browser clients. This method will
349 // generate the entropy source value if it has not been called before.
350 int GetLowEntropySource();
352 // Returns the first entropy source that was returned by this service since
353 // start up, or NONE if neither was returned yet. This is exposed for testing
355 EntropySourceReturned entropy_source_returned() const {
356 return entropy_source_returned_;
359 // When we start a new version of Chromium (different from our last run), we
360 // need to discard the old crash stats so that we don't attribute crashes etc.
361 // in the old version to the current version (via current logs).
362 // Without this, a common reason to finally start a new version is to crash
363 // the old version (after an autoupdate has arrived), and so we'd bias
364 // initial results towards showing crashes :-(.
365 static void DiscardOldStabilityStats(PrefService* local_state);
366 #if defined(OS_ANDROID)
367 static void DiscardOldStabilityStatsAndroid(PrefService* local_state);
368 #endif // defined(OS_ANDROID)
370 // Turns recording on or off.
371 // DisableRecording() also forces a persistent save of logging state (if
372 // anything has been recorded, or transmitted).
373 void EnableRecording();
374 void DisableRecording();
376 // If in_idle is true, sets idle_since_last_transmission to true.
377 // If in_idle is false and idle_since_last_transmission_ is true, sets
378 // idle_since_last_transmission to false and starts the timer (provided
379 // starting the timer is permitted).
380 void HandleIdleSinceLastTransmission(bool in_idle);
382 // Set up client ID, session ID, etc.
383 void InitializeMetricsState(ReportingState reporting_state);
385 // Generates a new client ID to use to identify self to metrics server.
386 static std::string GenerateClientID();
388 // Schedule the next save of LocalState information. This is called
389 // automatically by the task that performs each save to schedule the next one.
390 void ScheduleNextStateSave();
392 // Save the LocalState information immediately. This should not be called by
393 // anybody other than the scheduler to avoid doing too many writes. When you
394 // make a change, call ScheduleNextStateSave() instead.
395 void SaveLocalState();
397 // Opens a new log for recording user experience metrics.
400 // Closes out the current log after adding any last information.
401 void CloseCurrentLog();
403 // Pushes the text of the current and staged logs into persistent storage.
404 // Called when Chrome shuts down.
405 void PushPendingLogsToPersistentStorage();
407 // Ensures that scheduler is running, assuming the current settings are such
408 // that metrics should be reported. If not, this is a no-op.
409 void StartSchedulerIfNecessary();
411 // Starts the process of uploading metrics data.
412 void StartScheduledUpload();
414 // Starts collecting any data that should be added to a log just before it is
416 void StartFinalLogInfoCollection();
417 // Callbacks for various stages of final log info collection. Do not call
419 void OnMemoryDetailCollectionDone();
420 void OnHistogramSynchronizationDone();
421 void OnFinalLogInfoCollectionDone();
423 // Either closes the current log or creates and closes the initial log
424 // (depending on |state_|), and stages it for upload.
427 // Prepares the initial stability log, which is only logged when the previous
428 // run of Chrome crashed. This log contains any stability metrics left over
429 // from that previous run, and only these stability metrics. It uses the
430 // system profile from the previous session.
431 void PrepareInitialStabilityLog();
433 // Prepares the initial metrics log, which includes startup histograms and
434 // profiler data, as well as incremental stability-related metrics.
435 void PrepareInitialMetricsLog(MetricsLog::LogType log_type);
437 // Uploads the currently staged log (which must be non-null).
438 void SendStagedLog();
440 // Prepared the staged log to be passed to the server. Upon return,
441 // current_fetch_ should be reset with its upload data set to a compressed
442 // copy of the staged log.
443 void PrepareFetchWithStagedLog();
445 // Implementation of net::URLFetcherDelegate. Called after transmission
446 // completes (either successfully or with failure).
447 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
449 // Reads, increments and then sets the specified integer preference.
450 void IncrementPrefValue(const char* path);
452 // Reads, increments and then sets the specified long preference that is
453 // stored as a string.
454 void IncrementLongPrefsValue(const char* path);
456 // Records a renderer process crash.
457 void LogRendererCrash(content::RenderProcessHost* host,
458 base::TerminationStatus status,
461 // Records a renderer process hang.
462 void LogRendererHang();
464 // Records that the browser was shut down cleanly.
465 void LogCleanShutdown();
467 // Returns reference to ChildProcessStats corresponding to |data|.
468 ChildProcessStats& GetChildProcessStats(
469 const content::ChildProcessData& data);
471 // Saves plugin-related updates from the in-object buffer to Local State
472 // for retrieval next time we send a Profile log (generally next launch).
473 void RecordPluginChanges(PrefService* pref);
475 // Records state that should be periodically saved, like uptime and
476 // buffered plugin stability statistics.
477 void RecordCurrentState(PrefService* pref);
479 // Logs the initiation of a page load and uses |web_contents| to do
480 // additional logging of the type of page loaded.
481 void LogLoadStarted(content::WebContents* web_contents);
483 // Checks whether a notification can be logged.
484 bool CanLogNotification();
486 // Sets the value of the specified path in prefs and schedules a save.
487 void RecordBooleanPrefValue(const char* path, bool value);
489 // Returns true if process of type |type| should be counted as a plugin
490 // process, and false otherwise.
491 static bool IsPluginProcess(int process_type);
493 // Returns a list of synthetic field trials that were active for the entire
494 // duration of the current log.
495 void GetCurrentSyntheticFieldTrials(
496 std::vector<chrome_variations::ActiveGroupId>* synthetic_trials);
498 base::ActionCallback action_callback_;
500 content::NotificationRegistrar registrar_;
502 // Indicate whether recording and reporting are currently happening.
503 // These should not be set directly, but by calling SetRecording and
505 bool recording_active_;
506 bool reporting_active_;
508 // Indicate whether test mode is enabled, where the initial log should never
509 // be cut, and logs are neither persisted nor uploaded.
510 bool test_mode_active_;
512 // The progression of states made by the browser are recorded in the following
516 // Whether the initial stability log has been recorded during startup.
517 bool has_initial_stability_log_;
519 // Chrome OS hardware class (e.g., hardware qualification ID). This
520 // class identifies the configured system components such as CPU,
521 // WiFi adapter, etc. For non Chrome OS hosts, this will be an
523 std::string hardware_class_;
525 // The list of plugins which was retrieved on the file thread.
526 std::vector<content::WebPluginInfo> plugins_;
528 // Google Update statistics, which were retrieved on a blocking pool thread.
529 GoogleUpdateMetrics google_update_metrics_;
531 // The initial metrics log, used to record startup metrics (histograms and
532 // profiler data). Note that if a crash occurred in the previous session, an
533 // initial stability log may be sent before this.
534 scoped_ptr<MetricsLog> initial_metrics_log_;
536 // The outstanding transmission appears as a URL Fetch operation.
537 scoped_ptr<net::URLFetcher> current_fetch_;
539 // The TCP/UDP echo server to collect network connectivity stats.
540 std::string network_stats_server_;
542 // The HTTP pipelining test server.
543 std::string http_pipelining_test_server_;
545 // The identifier that's sent to the server with the log reports.
546 std::string client_id_;
548 // The non-identifying low entropy source value.
549 int low_entropy_source_;
551 // Whether the MetricsService object has received any notifications since
552 // the last time a transmission was sent.
553 bool idle_since_last_transmission_;
555 // A number that identifies the how many times the app has been launched.
558 // Maps WebContentses (corresponding to tabs) or Browsers (corresponding to
559 // Windows) to a unique integer that we will use to identify them.
560 // |next_window_id_| is used to track which IDs we have used so far.
561 typedef std::map<uintptr_t, int> WindowMap;
562 WindowMap window_map_;
565 // Buffer of child process notifications for quick access.
566 std::map<base::string16, ChildProcessStats> child_process_stats_buffer_;
568 // Weak pointers factory used to post task on different threads. All weak
569 // pointers managed by this factory have the same lifetime as MetricsService.
570 base::WeakPtrFactory<MetricsService> self_ptr_factory_;
572 // Weak pointers factory used for saving state. All weak pointers managed by
573 // this factory are invalidated in ScheduleNextStateSave.
574 base::WeakPtrFactory<MetricsService> state_saver_factory_;
576 // The scheduler for determining when uploads should happen.
577 scoped_ptr<MetricsReportingScheduler> scheduler_;
579 // Indicates that an asynchronous reporting step is running.
580 // This is used only for debugging.
581 bool waiting_for_asynchronous_reporting_step_;
583 // Number of async histogram fetch requests in progress.
584 int num_async_histogram_fetches_in_progress_;
586 #if defined(OS_CHROMEOS)
587 // The external metric service is used to log ChromeOS UMA events.
588 scoped_refptr<chromeos::ExternalMetrics> external_metrics_;
591 // The last entropy source returned by this service, used for testing.
592 EntropySourceReturned entropy_source_returned_;
594 // Stores the time of the last call to |GetIncrementalUptime()|.
595 base::TimeTicks last_updated_time_;
597 // Execution phase the browser is in.
598 static ExecutionPhase execution_phase_;
600 // Reduntant marker to check that we completed our shutdown, and set the
601 // exited-cleanly bit in the prefs.
602 static ShutdownCleanliness clean_shutdown_status_;
604 // Field trial groups that map to Chrome configuration states.
605 SyntheticTrialGroups synthetic_trial_groups_;
607 FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, ClientIdCorrectlyFormatted);
608 FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, IsPluginProcess);
609 FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, LowEntropySource0NotReset);
610 FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest,
611 PermutedEntropyCacheClearedWhenLowEntropyReset);
612 FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, RegisterSyntheticTrial);
613 FRIEND_TEST_ALL_PREFIXES(MetricsServiceBrowserTest,
614 CheckLowEntropySourceUsed);
615 FRIEND_TEST_ALL_PREFIXES(MetricsServiceReportingTest,
616 CheckHighEntropySourceUsed);
618 DISALLOW_COPY_AND_ASSIGN(MetricsService);
621 // This class limits and documents access to the IsMetricsReportingEnabled()
622 // method. Since the method is private, each user has to be explicitly declared
623 // as a 'friend' below.
624 class MetricsServiceHelper {
626 friend bool prerender::IsOmniboxEnabled(Profile* profile);
627 friend class extensions::ExtensionDownloader;
628 friend class extensions::ManifestFetchData;
630 // Returns true if prefs::kMetricsReportingEnabled is set.
631 static bool IsMetricsReportingEnabled();
633 DISALLOW_IMPLICIT_CONSTRUCTORS(MetricsServiceHelper);
636 #endif // CHROME_BROWSER_METRICS_METRICS_SERVICE_H_