blob: 256941b64bf9d70f665ede3917ff4a95928b7679 [file] [log] [blame]
[email protected]d6147bd2014-06-11 01:58:191// Copyright 2014 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
initial.commit09911bf2008-07-26 23:55:295//------------------------------------------------------------------------------
6// Description of the life cycle of a instance of MetricsService.
7//
8// OVERVIEW
9//
[email protected]e3eb0c42013-04-18 06:18:5810// A MetricsService instance is typically created at application startup. It is
11// the central controller for the acquisition of log data, and the automatic
initial.commit09911bf2008-07-26 23:55:2912// transmission of that log data to an external server. Its major job is to
13// manage logs, grouping them for transmission, and transmitting them. As part
14// of its grouping, MS finalizes logs by including some just-in-time gathered
15// memory statistics, snapshotting the current stats of numerous histograms,
[email protected]e3eb0c42013-04-18 06:18:5816// closing the logs, translating to protocol buffer format, and compressing the
17// results for transmission. Transmission includes submitting a compressed log
18// as data in a URL-post, and retransmitting (or retaining at process
19// termination) if the attempted transmission failed. Retention across process
20// terminations is done using the the PrefServices facilities. The retained logs
21// (the ones that never got transmitted) are compressed and base64-encoded
22// before being persisted.
initial.commit09911bf2008-07-26 23:55:2923//
[email protected]281d2882009-01-20 20:32:4224// Logs fall into one of two categories: "initial logs," and "ongoing logs."
[email protected]80a8f312013-12-16 18:00:3025// There is at most one initial log sent for each complete run of Chrome (from
26// startup, to browser shutdown). An initial log is generally transmitted some
27// short time (1 minute?) after startup, and includes stats such as recent crash
28// info, the number and types of plugins, etc. The external server's response
29// to the initial log conceptually tells this MS if it should continue
30// transmitting logs (during this session). The server response can actually be
31// much more detailed, and always includes (at a minimum) how often additional
32// ongoing logs should be sent.
initial.commit09911bf2008-07-26 23:55:2933//
34// After the above initial log, a series of ongoing logs will be transmitted.
35// The first ongoing log actually begins to accumulate information stating when
36// the MS was first constructed. Note that even though the initial log is
37// commonly sent a full minute after startup, the initial log does not include
38// much in the way of user stats. The most common interlog period (delay)
[email protected]3a668152013-06-21 23:56:4239// is 30 minutes. That time period starts when the first user action causes a
initial.commit09911bf2008-07-26 23:55:2940// logging event. This means that if there is no user action, there may be long
[email protected]281d2882009-01-20 20:32:4241// periods without any (ongoing) log transmissions. Ongoing logs typically
initial.commit09911bf2008-07-26 23:55:2942// contain very detailed records of user activities (ex: opened tab, closed
43// tab, fetched URL, maximized window, etc.) In addition, just before an
44// ongoing log is closed out, a call is made to gather memory statistics. Those
45// memory statistics are deposited into a histogram, and the log finalization
46// code is then called. In the finalization, a call to a Histogram server
47// acquires a list of all local histograms that have been flagged for upload
[email protected]80a8f312013-12-16 18:00:3048// to the UMA server. The finalization also acquires the most recent number
[email protected]281d2882009-01-20 20:32:4249// of page loads, along with any counts of renderer or plugin crashes.
initial.commit09911bf2008-07-26 23:55:2950//
51// When the browser shuts down, there will typically be a fragment of an ongoing
[email protected]80a8f312013-12-16 18:00:3052// log that has not yet been transmitted. At shutdown time, that fragment is
53// closed (including snapshotting histograms), and persisted, for potential
54// transmission during a future run of the product.
initial.commit09911bf2008-07-26 23:55:2955//
56// There are two slightly abnormal shutdown conditions. There is a
57// "disconnected scenario," and a "really fast startup and shutdown" scenario.
58// In the "never connected" situation, the user has (during the running of the
59// process) never established an internet connection. As a result, attempts to
60// transmit the initial log have failed, and a lot(?) of data has accumulated in
61// the ongoing log (which didn't yet get closed, because there was never even a
62// contemplation of sending it). There is also a kindred "lost connection"
63// situation, where a loss of connection prevented an ongoing log from being
64// transmitted, and a (still open) log was stuck accumulating a lot(?) of data,
65// while the earlier log retried its transmission. In both of these
66// disconnected situations, two logs need to be, and are, persistently stored
67// for future transmission.
68//
69// The other unusual shutdown condition, termed "really fast startup and
70// shutdown," involves the deliberate user termination of the process before
71// the initial log is even formed or transmitted. In that situation, no logging
72// is done, but the historical crash statistics remain (unlogged) for inclusion
73// in a future run's initial log. (i.e., we don't lose crash stats).
74//
75// With the above overview, we can now describe the state machine's various
[email protected]80a8f312013-12-16 18:00:3076// states, based on the State enum specified in the state_ member. Those states
initial.commit09911bf2008-07-26 23:55:2977// are:
78//
Steven Holte2c294a32015-03-12 21:45:0379// INITIALIZED, // Constructor was called.
80// INIT_TASK_SCHEDULED, // Waiting for deferred init tasks to finish.
81// INIT_TASK_DONE, // Waiting for timer to send initial log.
82// SENDING_LOGS, // Sending logs and creating new ones when we run out.
initial.commit09911bf2008-07-26 23:55:2983//
84// In more detail, we have:
85//
86// INITIALIZED, // Constructor was called.
87// The MS has been constructed, but has taken no actions to compose the
88// initial log.
89//
[email protected]80a8f312013-12-16 18:00:3090// INIT_TASK_SCHEDULED, // Waiting for deferred init tasks to finish.
initial.commit09911bf2008-07-26 23:55:2991// Typically about 30 seconds after startup, a task is sent to a second thread
[email protected]85ed9d42010-06-08 22:37:4492// (the file thread) to perform deferred (lower priority and slower)
93// initialization steps such as getting the list of plugins. That task will
94// (when complete) make an async callback (via a Task) to indicate the
95// completion.
initial.commit09911bf2008-07-26 23:55:2996//
[email protected]85ed9d42010-06-08 22:37:4497// INIT_TASK_DONE, // Waiting for timer to send initial log.
initial.commit09911bf2008-07-26 23:55:2998// The callback has arrived, and it is now possible for an initial log to be
99// created. This callback typically arrives back less than one second after
[email protected]85ed9d42010-06-08 22:37:44100// the deferred init task is dispatched.
initial.commit09911bf2008-07-26 23:55:29101//
Steven Holte2c294a32015-03-12 21:45:03102// SENDING_LOGS, // Sending logs an creating new ones when we run out.
103// Logs from previous sessions have been loaded, and initial logs have been
104// created (an optional stability log and the first metrics log). We will
105// send all of these logs, and when run out, we will start cutting new logs
106// to send. We will also cut a new log if we expect a shutdown.
[email protected]80a8f312013-12-16 18:00:30107//
Steven Holte2c294a32015-03-12 21:45:03108// The progression through the above states is simple, and sequential.
109// States proceed from INITIAL to SENDING_LOGS, and remain in the latter until
110// shutdown.
initial.commit09911bf2008-07-26 23:55:29111//
Steven Holte2c294a32015-03-12 21:45:03112// Also note that whenever we successfully send a log, we mirror the list
[email protected]cac267c2011-09-29 15:18:10113// of logs into the PrefService. This ensures that IF we crash, we won't start
114// up and retransmit our old logs again.
initial.commit09911bf2008-07-26 23:55:29115//
116// Due to race conditions, it is always possible that a log file could be sent
117// twice. For example, if a log file is sent, but not yet acknowledged by
118// the external server, and the user shuts down, then a copy of the log may be
119// saved for re-transmission. These duplicates could be filtered out server
[email protected]281d2882009-01-20 20:32:42120// side, but are not expected to be a significant problem.
initial.commit09911bf2008-07-26 23:55:29121//
122//
123//------------------------------------------------------------------------------
124
[email protected]d6147bd2014-06-11 01:58:19125#include "components/metrics/metrics_service.h"
[email protected]40bcc302009-03-02 20:50:39126
avi26062922015-12-26 00:14:18127#include <stddef.h>
dchengd99c42a2016-04-21 21:54:13128
dcheng51606352015-12-26 21:16:23129#include <algorithm>
130#include <utility>
avi26062922015-12-26 00:14:18131
[email protected]7f7f1962011-04-20 15:58:16132#include "base/bind.h"
133#include "base/callback.h"
skyostilb0daa012015-06-02 19:03:48134#include "base/location.h"
dchengd99c42a2016-04-21 21:54:13135#include "base/memory/ptr_util.h"
[email protected]acc2ce5512014-05-22 18:29:13136#include "base/metrics/histogram_base.h"
asvitkine454600f2015-06-16 16:34:50137#include "base/metrics/histogram_macros.h"
[email protected]acc2ce5512014-05-22 18:29:13138#include "base/metrics/histogram_samples.h"
bcwhite33d95806a2016-03-16 02:37:45139#include "base/metrics/persistent_histogram_allocator.h"
[email protected]1026afd2013-03-20 14:28:54140#include "base/metrics/sparse_histogram.h"
[email protected]567d30e2012-07-13 21:48:29141#include "base/metrics/statistics_recorder.h"
skyostilb0daa012015-06-02 19:03:48142#include "base/single_thread_task_runner.h"
Robert Kaplowd45b6202017-07-20 02:01:46143#include "base/strings/string_piece.h"
Steven Holte971b0592017-10-12 15:28:26144#include "base/threading/sequenced_task_runner_handle.h"
[email protected]64b8652c2014-07-16 19:14:28145#include "base/time/time.h"
avi26062922015-12-26 00:14:18146#include "build/build_config.h"
holte1bf273c2017-02-23 00:22:28147#include "components/metrics/environment_recorder.h"
Steven Holte5c6dd632017-07-19 23:25:49148#include "components/metrics/field_trials_provider.h"
[email protected]91b1d912014-06-05 10:52:08149#include "components/metrics/metrics_log.h"
[email protected]064107e2014-05-02 00:59:06150#include "components/metrics/metrics_log_manager.h"
[email protected]0d5a61a82014-05-31 22:28:34151#include "components/metrics/metrics_log_uploader.h"
[email protected]7f07db62014-05-15 01:12:45152#include "components/metrics/metrics_pref_names.h"
holte68395852017-01-10 20:40:21153#include "components/metrics/metrics_rotation_scheduler.h"
[email protected]73929422014-05-22 08:19:05154#include "components/metrics/metrics_service_client.h"
[email protected]16a30912014-06-04 00:20:04155#include "components/metrics/metrics_state_manager.h"
Steven Holted0429a702017-08-03 08:56:17156#include "components/metrics/persistent_system_profile.h"
holte1bf273c2017-02-23 00:22:28157#include "components/metrics/stability_metrics_provider.h"
holte567a16f22017-01-06 01:53:45158#include "components/metrics/url_constants.h"
brettwf00b9b42016-02-01 22:11:38159#include "components/prefs/pref_registry_simple.h"
160#include "components/prefs/pref_service.h"
[email protected]50ae9f12013-08-29 18:03:22161#include "components/variations/entropy_provider.h"
initial.commit09911bf2008-07-26 23:55:29162
asvitkinecbd420732014-08-26 22:15:40163namespace metrics {
[email protected]e1acf6f2008-10-27 20:43:33164
holte6e36a3d2017-02-02 22:41:10165namespace {
166
[email protected]7f7f1962011-04-20 15:58:16167// The delay, in seconds, after starting recording before doing expensive
168// initialization work.
[email protected]12180f82012-10-10 21:13:30169#if defined(OS_ANDROID) || defined(OS_IOS)
170// On mobile devices, a significant portion of sessions last less than a minute.
171// Use a shorter timer on these platforms to avoid losing data.
172// TODO(dfalcantara): To avoid delaying startup, tighten up initialization so
173// that it occurs after the user gets their initial page.
174const int kInitializationDelaySeconds = 5;
175#else
[email protected]fe58acc22012-02-29 01:29:58176const int kInitializationDelaySeconds = 30;
[email protected]12180f82012-10-10 21:13:30177#endif
[email protected]252873ef2008-08-04 21:59:45178
hashimotoa5c00e28d2015-03-27 06:28:37179#if defined(OS_ANDROID) || defined(OS_IOS)
erikwright65b58df2014-09-12 00:05:28180void MarkAppCleanShutdownAndCommit(CleanExitBeacon* clean_exit_beacon,
181 PrefService* local_state) {
182 clean_exit_beacon->WriteBeaconValue(true);
holtea27eadf2017-01-26 01:58:59183 ExecutionPhaseManager(local_state).OnAppEnterBackground();
[email protected]84c384e2013-03-01 23:20:19184 // Start writing right away (write happens on a different thread).
[email protected]24f81ca2014-05-26 15:59:34185 local_state->CommitPendingWrite();
[email protected]84c384e2013-03-01 23:20:19186}
hashimotoa5c00e28d2015-03-27 06:28:37187#endif // defined(OS_ANDROID) || defined(OS_IOS)
[email protected]84c384e2013-03-01 23:20:19188
[email protected]20f999b52012-08-24 22:32:59189} // namespace
initial.commit09911bf2008-07-26 23:55:29190
[email protected]c0c55e92011-09-10 18:47:30191// static
192MetricsService::ShutdownCleanliness MetricsService::clean_shutdown_status_ =
193 MetricsService::CLEANLY_SHUTDOWN;
194
initial.commit09911bf2008-07-26 23:55:29195// static
[email protected]b1de2c72013-02-06 02:45:47196void MetricsService::RegisterPrefs(PrefRegistrySimple* registry) {
holte1bf273c2017-02-23 00:22:28197 CleanExitBeacon::RegisterPrefs(registry);
asvitkinea63d19e2014-10-24 16:19:39198 MetricsStateManager::RegisterPrefs(registry);
[email protected]91b1d912014-06-05 10:52:08199 MetricsLog::RegisterPrefs(registry);
holte1bf273c2017-02-23 00:22:28200 StabilityMetricsProvider::RegisterPrefs(registry);
holte1bf273c2017-02-23 00:22:28201 ExecutionPhaseManager::RegisterPrefs(registry);
holte77d815b2017-03-27 21:27:37202 MetricsReportingService::RegisterPrefs(registry);
[email protected]39076642014-05-05 20:32:55203
asvitkinea63d19e2014-10-24 16:19:39204 registry->RegisterIntegerPref(prefs::kMetricsSessionID, -1);
[email protected]0f2f7792013-11-28 16:09:14205
asvitkinea63d19e2014-10-24 16:19:39206 registry->RegisterInt64Pref(prefs::kUninstallLaunchCount, 0);
207 registry->RegisterInt64Pref(prefs::kUninstallMetricsUptimeSec, 0);
initial.commit09911bf2008-07-26 23:55:29208}
209
asvitkinea63d19e2014-10-24 16:19:39210MetricsService::MetricsService(MetricsStateManager* state_manager,
211 MetricsServiceClient* client,
[email protected]24f81ca2014-05-26 15:59:34212 PrefService* local_state)
holtea3b24112017-03-14 02:08:24213 : reporting_service_(client, local_state),
[email protected]acc2ce5512014-05-22 18:29:13214 histogram_snapshot_manager_(this),
[email protected]7f07db62014-05-15 01:12:45215 state_manager_(state_manager),
[email protected]728de072014-05-21 09:20:32216 client_(client),
[email protected]24f81ca2014-05-26 15:59:34217 local_state_(local_state),
wittman622851e2015-07-31 18:13:40218 recording_state_(UNSET),
[email protected]410938e02012-10-24 16:33:59219 test_mode_active_(false),
[email protected]d01b8732008-10-16 02:18:07220 state_(INITIALIZED),
[email protected]d01b8732008-10-16 02:18:07221 idle_since_last_transmission_(false),
[email protected]80a8f312013-12-16 18:00:30222 session_id_(-1),
holte57fcaed2017-01-23 22:14:31223 self_ptr_factory_(this) {
Steven Holte971b0592017-10-12 15:28:26224 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]39076642014-05-05 20:32:55225 DCHECK(state_manager_);
[email protected]728de072014-05-21 09:20:32226 DCHECK(client_);
[email protected]24f81ca2014-05-26 15:59:34227 DCHECK(local_state_);
[email protected]64b8652c2014-07-16 19:14:28228
Steven Holte5c6dd632017-07-19 23:25:49229 RegisterMetricsProvider(
230 base::MakeUnique<StabilityMetricsProvider>(local_state_));
231
Steven Holted0429a702017-08-03 08:56:17232 RegisterMetricsProvider(state_manager_->GetProvider());
233
Steven Holte5c6dd632017-07-19 23:25:49234 RegisterMetricsProvider(base::MakeUnique<variations::FieldTrialsProvider>(
Robert Kaplowd45b6202017-07-20 02:01:46235 &synthetic_trial_registry_, base::StringPiece()));
initial.commit09911bf2008-07-26 23:55:29236}
237
238MetricsService::~MetricsService() {
[email protected]410938e02012-10-24 16:33:59239 DisableRecording();
initial.commit09911bf2008-07-26 23:55:29240}
241
[email protected]39076642014-05-05 20:32:55242void MetricsService::InitializeMetricsRecordingState() {
holtea3b24112017-03-14 02:08:24243 reporting_service_.Initialize();
[email protected]39076642014-05-05 20:32:55244 InitializeMetricsState();
[email protected]80a8f312013-12-16 18:00:30245
gayaned52ca402015-02-23 21:23:06246 base::Closure upload_callback =
247 base::Bind(&MetricsService::StartScheduledUpload,
248 self_ptr_factory_.GetWeakPtr());
holte68395852017-01-10 20:40:21249
holtec1b97312017-02-24 21:37:10250 rotation_scheduler_.reset(new MetricsRotationScheduler(
251 upload_callback,
252 // MetricsServiceClient outlives MetricsService, and
253 // MetricsRotationScheduler is tied to the lifetime of |this|.
254 base::Bind(&MetricsServiceClient::GetStandardUploadInterval,
255 base::Unretained(client_))));
dhsharpb0073a22016-02-18 21:54:09256
Steven Holtec35411dc2017-07-28 04:22:14257 delegating_provider_.Init();
[email protected]80a8f312013-12-16 18:00:30258}
259
[email protected]d01b8732008-10-16 02:18:07260void MetricsService::Start() {
[email protected]b1c8dc02011-04-13 18:32:04261 HandleIdleSinceLastTransmission(false);
[email protected]410938e02012-10-24 16:33:59262 EnableRecording();
263 EnableReporting();
[email protected]d01b8732008-10-16 02:18:07264}
265
[email protected]410938e02012-10-24 16:33:59266void MetricsService::StartRecordingForTests() {
267 test_mode_active_ = true;
268 EnableRecording();
269 DisableReporting();
[email protected]d01b8732008-10-16 02:18:07270}
271
272void MetricsService::Stop() {
[email protected]b1c8dc02011-04-13 18:32:04273 HandleIdleSinceLastTransmission(false);
[email protected]410938e02012-10-24 16:33:59274 DisableReporting();
275 DisableRecording();
[email protected]410938e02012-10-24 16:33:59276}
277
278void MetricsService::EnableReporting() {
holtea3b24112017-03-14 02:08:24279 if (reporting_service_.reporting_active())
[email protected]410938e02012-10-24 16:33:59280 return;
holtea3b24112017-03-14 02:08:24281 reporting_service_.EnableReporting();
[email protected]410938e02012-10-24 16:33:59282 StartSchedulerIfNecessary();
283}
284
285void MetricsService::DisableReporting() {
holtea3b24112017-03-14 02:08:24286 reporting_service_.DisableReporting();
[email protected]d01b8732008-10-16 02:18:07287}
288
[email protected]edafd4c2011-05-10 17:18:53289std::string MetricsService::GetClientId() {
[email protected]39076642014-05-05 20:32:55290 return state_manager_->client_id();
[email protected]edafd4c2011-05-10 17:18:53291}
292
avi26062922015-12-26 00:14:18293int64_t MetricsService::GetInstallDate() {
Steven Holte8e9db0ca2017-08-11 01:20:08294 return state_manager_->GetInstallDate();
olivierrobinc3dfc5b2015-04-07 19:12:00295}
296
drogerb8d286e42015-07-08 09:07:09297bool MetricsService::WasLastShutdownClean() const {
Ilya Sherman6c6c8332017-07-11 22:39:22298 return state_manager_->clean_exit_beacon()->exited_cleanly();
drogerb8d286e42015-07-08 09:07:09299}
300
[email protected]410938e02012-10-24 16:33:59301void MetricsService::EnableRecording() {
Steven Holte971b0592017-10-12 15:28:26302 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
initial.commit09911bf2008-07-26 23:55:29303
wittman622851e2015-07-31 18:13:40304 if (recording_state_ == ACTIVE)
initial.commit09911bf2008-07-26 23:55:29305 return;
wittman622851e2015-07-31 18:13:40306 recording_state_ = ACTIVE;
initial.commit09911bf2008-07-26 23:55:29307
[email protected]39076642014-05-05 20:32:55308 state_manager_->ForceClientIdCreation();
[email protected]9d1b0152014-07-09 18:53:22309 client_->SetMetricsClientId(state_manager_->client_id());
Steven Holted0429a702017-08-03 08:56:17310
311 SystemProfileProto system_profile;
312 MetricsLog::RecordCoreSystemProfile(client_, &system_profile);
313 GlobalPersistentSystemProfile::GetInstance()->SetSystemProfile(
314 system_profile, /*complete=*/false);
315
[email protected]410938e02012-10-24 16:33:59316 if (!log_manager_.current_log())
317 OpenNewLog();
[email protected]005ef3e2009-05-22 20:55:46318
Steven Holtec35411dc2017-07-28 04:22:14319 delegating_provider_.OnRecordingEnabled();
[email protected]85791b0b2014-05-20 15:18:58320
[email protected]e6e30ac2014-01-13 21:24:39321 base::RemoveActionCallback(action_callback_);
[email protected]dd98f392013-02-04 13:03:22322 action_callback_ = base::Bind(&MetricsService::OnUserAction,
323 base::Unretained(this));
[email protected]e6e30ac2014-01-13 21:24:39324 base::AddActionCallback(action_callback_);
[email protected]410938e02012-10-24 16:33:59325}
326
327void MetricsService::DisableRecording() {
Steven Holte971b0592017-10-12 15:28:26328 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]410938e02012-10-24 16:33:59329
wittman622851e2015-07-31 18:13:40330 if (recording_state_ == INACTIVE)
[email protected]410938e02012-10-24 16:33:59331 return;
wittman622851e2015-07-31 18:13:40332 recording_state_ = INACTIVE;
[email protected]410938e02012-10-24 16:33:59333
[email protected]e6e30ac2014-01-13 21:24:39334 base::RemoveActionCallback(action_callback_);
[email protected]85791b0b2014-05-20 15:18:58335
Steven Holtec35411dc2017-07-28 04:22:14336 delegating_provider_.OnRecordingDisabled();
[email protected]85791b0b2014-05-20 15:18:58337
[email protected]410938e02012-10-24 16:33:59338 PushPendingLogsToPersistentStorage();
initial.commit09911bf2008-07-26 23:55:29339}
340
[email protected]d01b8732008-10-16 02:18:07341bool MetricsService::recording_active() const {
Steven Holte971b0592017-10-12 15:28:26342 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
wittman622851e2015-07-31 18:13:40343 return recording_state_ == ACTIVE;
initial.commit09911bf2008-07-26 23:55:29344}
345
[email protected]d01b8732008-10-16 02:18:07346bool MetricsService::reporting_active() const {
Steven Holte971b0592017-10-12 15:28:26347 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
holtea3b24112017-03-14 02:08:24348 return reporting_service_.reporting_active();
349}
350
351bool MetricsService::has_unsent_logs() const {
352 return reporting_service_.metrics_log_store()->has_unsent_logs();
initial.commit09911bf2008-07-26 23:55:29353}
354
[email protected]acc2ce5512014-05-22 18:29:13355void MetricsService::RecordDelta(const base::HistogramBase& histogram,
356 const base::HistogramSamples& snapshot) {
[email protected]acc2ce5512014-05-22 18:29:13357 log_manager_.current_log()->RecordHistogramDelta(histogram.histogram_name(),
358 snapshot);
[email protected]acc2ce5512014-05-22 18:29:13359}
360
[email protected]d01b8732008-10-16 02:18:07361void MetricsService::HandleIdleSinceLastTransmission(bool in_idle) {
362 // If there wasn't a lot of action, maybe the computer was asleep, in which
363 // case, the log transmissions should have stopped. Here we start them up
364 // again.
[email protected]cac78842008-11-27 01:02:20365 if (!in_idle && idle_since_last_transmission_)
[email protected]7f7f1962011-04-20 15:58:16366 StartSchedulerIfNecessary();
[email protected]cac78842008-11-27 01:02:20367 idle_since_last_transmission_ = in_idle;
initial.commit09911bf2008-07-26 23:55:29368}
369
[email protected]d7ea39e2014-05-22 03:59:18370void MetricsService::OnApplicationNotIdle() {
wittman622851e2015-07-31 18:13:40371 if (recording_state_ == ACTIVE)
[email protected]d7ea39e2014-05-22 03:59:18372 HandleIdleSinceLastTransmission(false);
373}
374
initial.commit09911bf2008-07-26 23:55:29375void MetricsService::RecordStartOfSessionEnd() {
holte6d341162016-12-19 21:42:42376 LogCleanShutdown(false);
initial.commit09911bf2008-07-26 23:55:29377}
378
379void MetricsService::RecordCompletedSessionEnd() {
holte6d341162016-12-19 21:42:42380 LogCleanShutdown(true);
initial.commit09911bf2008-07-26 23:55:29381}
382
[email protected]410938e02012-10-24 16:33:59383#if defined(OS_ANDROID) || defined(OS_IOS)
[email protected]117fbdf22012-06-26 18:36:39384void MetricsService::OnAppEnterBackground() {
holtec1b97312017-02-24 21:37:10385 rotation_scheduler_->Stop();
holtea3b24112017-03-14 02:08:24386 reporting_service_.Stop();
[email protected]117fbdf22012-06-26 18:36:39387
Ilya Sherman6c6c8332017-07-11 22:39:22388 MarkAppCleanShutdownAndCommit(state_manager_->clean_exit_beacon(),
389 local_state_);
[email protected]117fbdf22012-06-26 18:36:39390
bmcquade6a49bed2016-07-27 19:25:56391 // Give providers a chance to persist histograms as part of being
392 // backgrounded.
Steven Holtec35411dc2017-07-28 04:22:14393 delegating_provider_.OnAppEnterBackground();
bmcquade6a49bed2016-07-27 19:25:56394
[email protected]117fbdf22012-06-26 18:36:39395 // At this point, there's no way of knowing when the process will be
396 // killed, so this has to be treated similar to a shutdown, closing and
397 // persisting all logs. Unlinke a shutdown, the state is primed to be ready
398 // to continue logging and uploading if the process does return.
Steven Holte2c294a32015-03-12 21:45:03399 if (recording_active() && state_ >= SENDING_LOGS) {
[email protected]117fbdf22012-06-26 18:36:39400 PushPendingLogsToPersistentStorage();
[email protected]410938e02012-10-24 16:33:59401 // Persisting logs closes the current log, so start recording a new log
402 // immediately to capture any background work that might be done before the
403 // process is killed.
404 OpenNewLog();
[email protected]117fbdf22012-06-26 18:36:39405 }
[email protected]117fbdf22012-06-26 18:36:39406}
407
408void MetricsService::OnAppEnterForeground() {
Ilya Sherman6c6c8332017-07-11 22:39:22409 state_manager_->clean_exit_beacon()->WriteBeaconValue(false);
holtea27eadf2017-01-26 01:58:59410 ExecutionPhaseManager(local_state_).OnAppEnterForeground();
[email protected]117fbdf22012-06-26 18:36:39411 StartSchedulerIfNecessary();
[email protected]117fbdf22012-06-26 18:36:39412}
[email protected]84c384e2013-03-01 23:20:19413#else
erikwrightcc98a7e02014-09-09 22:05:12414void MetricsService::LogNeedForCleanShutdown() {
Ilya Sherman6c6c8332017-07-11 22:39:22415 state_manager_->clean_exit_beacon()->WriteBeaconValue(false);
[email protected]84c384e2013-03-01 23:20:19416 // Redundant setting to be sure we call for a clean shutdown.
417 clean_shutdown_status_ = NEED_TO_SHUTDOWN;
418}
419#endif // defined(OS_ANDROID) || defined(OS_IOS)
[email protected]117fbdf22012-06-26 18:36:39420
[email protected]6d67ea0d2013-11-14 11:02:21421// static
[email protected]24f81ca2014-05-26 15:59:34422void MetricsService::SetExecutionPhase(ExecutionPhase execution_phase,
423 PrefService* local_state) {
holtea27eadf2017-01-26 01:58:59424 ExecutionPhaseManager(local_state).SetExecutionPhase(execution_phase);
[email protected]6d67ea0d2013-11-14 11:02:21425}
426
[email protected]7f7f1962011-04-20 15:58:16427void MetricsService::RecordBreakpadRegistration(bool success) {
holte1bf273c2017-02-23 00:22:28428 StabilityMetricsProvider(local_state_).RecordBreakpadRegistration(success);
[email protected]e73c01972008-08-13 00:18:24429}
430
431void MetricsService::RecordBreakpadHasDebugger(bool has_debugger) {
holte1bf273c2017-02-23 00:22:28432 StabilityMetricsProvider(local_state_)
433 .RecordBreakpadHasDebugger(has_debugger);
[email protected]e73c01972008-08-13 00:18:24434}
435
yiyaoliu14ef3ead2014-11-19 02:36:50436void MetricsService::ClearSavedStabilityMetrics() {
Steven Holtec35411dc2017-07-28 04:22:14437 delegating_provider_.ClearSavedStabilityMetrics();
yiyaoliu14ef3ead2014-11-19 02:36:50438}
439
olivierrobinc3dfc5b2015-04-07 19:12:00440void MetricsService::PushExternalLog(const std::string& log) {
holtea3b24112017-03-14 02:08:24441 log_store()->StoreLog(log, MetricsLog::ONGOING_LOG);
olivierrobinc3dfc5b2015-04-07 19:12:00442}
443
robliao7253fd22016-12-01 18:41:38444void MetricsService::UpdateMetricsUsagePrefs(const std::string& service_name,
445 int message_size,
446 bool is_cellular) {
Steven Holte971b0592017-10-12 15:28:26447 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
holtea3b24112017-03-14 02:08:24448 reporting_service_.UpdateMetricsUsagePrefs(service_name, message_size,
449 is_cellular);
gayane0b46091c2016-04-07 21:01:05450}
451
initial.commit09911bf2008-07-26 23:55:29452//------------------------------------------------------------------------------
453// private methods
454//------------------------------------------------------------------------------
455
456
457//------------------------------------------------------------------------------
458// Initialization methods
459
[email protected]39076642014-05-05 20:32:55460void MetricsService::InitializeMetricsState() {
avi26062922015-12-26 00:14:18461 const int64_t buildtime = MetricsLog::GetBuildTime();
asvitkineff3e2a62014-09-18 22:01:49462 const std::string version = client_->GetVersionString();
holte57fcaed2017-01-23 22:14:31463
asvitkineff3e2a62014-09-18 22:01:49464 bool version_changed = false;
holte1bf273c2017-02-23 00:22:28465 EnvironmentRecorder recorder(local_state_);
466 int64_t previous_buildtime = recorder.GetLastBuildtime();
467 std::string previous_version = recorder.GetLastVersion();
manzagopea99d1952016-09-08 23:40:05468 if (previous_buildtime != buildtime || previous_version != version) {
holte1bf273c2017-02-23 00:22:28469 recorder.SetBuildtimeAndVersion(buildtime, version);
asvitkineff3e2a62014-09-18 22:01:49470 version_changed = true;
471 }
initial.commit09911bf2008-07-26 23:55:29472
asvitkinea63d19e2014-10-24 16:19:39473 session_id_ = local_state_->GetInteger(prefs::kMetricsSessionID);
erikwright65b58df2014-09-12 00:05:28474
holte1bf273c2017-02-23 00:22:28475 StabilityMetricsProvider provider(local_state_);
Ilya Sherman6c6c8332017-07-11 22:39:22476 if (!state_manager_->clean_exit_beacon()->exited_cleanly()) {
holte1bf273c2017-02-23 00:22:28477 provider.LogCrash();
[email protected]c0c55e92011-09-10 18:47:30478 // Reset flag, and wait until we call LogNeedForCleanShutdown() before
479 // monitoring.
Ilya Sherman6c6c8332017-07-11 22:39:22480 state_manager_->clean_exit_beacon()->WriteBeaconValue(true);
holtea27eadf2017-01-26 01:58:59481 ExecutionPhaseManager manager(local_state_);
manzagop7c14de22016-11-25 16:19:34482 UMA_HISTOGRAM_SPARSE_SLOWLY("Chrome.Browser.CrashedExecutionPhase",
holtea27eadf2017-01-26 01:58:59483 static_cast<int>(manager.GetExecutionPhase()));
484 manager.SetExecutionPhase(ExecutionPhase::UNINITIALIZED_PHASE);
siggic179dd062014-09-10 17:02:31485 }
[email protected]6a6d0d12013-10-28 15:58:19486
Steven Holtec35411dc2017-07-28 04:22:14487 // HasPreviousSessionData is called first to ensure it is never bypassed.
manzagop780bb8b2016-10-21 14:21:16488 const bool is_initial_stability_log_required =
Steven Holtec35411dc2017-07-28 04:22:14489 delegating_provider_.HasPreviousSessionData() ||
Ilya Sherman6c6c8332017-07-11 22:39:22490 !state_manager_->clean_exit_beacon()->exited_cleanly();
Steven Holte2c294a32015-03-12 21:45:03491 bool has_initial_stability_log = false;
manzagop780bb8b2016-10-21 14:21:16492 if (is_initial_stability_log_required) {
siggic179dd062014-09-10 17:02:31493 // If the previous session didn't exit cleanly, or if any provider
494 // explicitly requests it, prepare an initial stability log -
495 // provided UMA is enabled.
manzagopea99d1952016-09-08 23:40:05496 if (state_manager_->IsMetricsReportingEnabled()) {
497 has_initial_stability_log = PrepareInitialStabilityLog(previous_version);
498 if (!has_initial_stability_log)
holte1bf273c2017-02-23 00:22:28499 provider.LogStabilityLogDeferred();
manzagopea99d1952016-09-08 23:40:05500 }
initial.commit09911bf2008-07-26 23:55:29501 }
[email protected]80a8f312013-12-16 18:00:30502
manzagop780bb8b2016-10-21 14:21:16503 // If the version changed, but no initial stability log was generated, clear
504 // the stability stats from the previous version (so that they don't get
asvitkineff3e2a62014-09-18 22:01:49505 // attributed to the current version). This could otherwise happen due to a
506 // number of different edge cases, such as if the last version crashed before
507 // it could save off a system profile or if UMA reporting is disabled (which
508 // normally results in stats being accumulated).
manzagop780bb8b2016-10-21 14:21:16509 if (version_changed && !has_initial_stability_log) {
yiyaoliu14ef3ead2014-11-19 02:36:50510 ClearSavedStabilityMetrics();
holte1bf273c2017-02-23 00:22:28511 provider.LogStabilityDataDiscarded();
manzagopea99d1952016-09-08 23:40:05512 }
asvitkineff3e2a62014-09-18 22:01:49513
manzagop780bb8b2016-10-21 14:21:16514 // If the version changed, the system profile is obsolete and needs to be
515 // cleared. This is to avoid the stability data misattribution that could
516 // occur if the current version crashed before saving its own system profile.
517 // Note however this clearing occurs only after preparing the initial
518 // stability log, an operation that requires the previous version's system
519 // profile. At this point, stability metrics pertaining to the previous
520 // version have been cleared.
holte1bf273c2017-02-23 00:22:28521 if (version_changed)
522 recorder.ClearEnvironmentFromPrefs();
manzagop780bb8b2016-10-21 14:21:16523
[email protected]80a8f312013-12-16 18:00:30524 // Update session ID.
525 ++session_id_;
asvitkinea63d19e2014-10-24 16:19:39526 local_state_->SetInteger(prefs::kMetricsSessionID, session_id_);
[email protected]80a8f312013-12-16 18:00:30527
holte1bf273c2017-02-23 00:22:28528 // Notify stability metrics providers about the launch.
529 provider.LogLaunch();
holtea27eadf2017-01-26 01:58:59530 SetExecutionPhase(ExecutionPhase::START_METRICS_RECORDING, local_state_);
holte1bf273c2017-02-23 00:22:28531 provider.CheckLastSessionEndCompleted();
initial.commit09911bf2008-07-26 23:55:29532
[email protected]076961c2014-03-12 22:23:56533 // Call GetUptimes() for the first time, thus allowing all later calls
534 // to record incremental uptimes accurately.
535 base::TimeDelta ignored_uptime_parameter;
536 base::TimeDelta startup_uptime;
[email protected]24f81ca2014-05-26 15:59:34537 GetUptimes(local_state_, &startup_uptime, &ignored_uptime_parameter);
[email protected]c68a2b9b2013-10-09 18:16:36538 DCHECK_EQ(0, startup_uptime.InMicroseconds());
[email protected]0bb1a622009-03-04 03:22:32539
540 // Bookkeeping for the uninstall metrics.
asvitkinea63d19e2014-10-24 16:19:39541 IncrementLongPrefsValue(prefs::kUninstallLaunchCount);
initial.commit09911bf2008-07-26 23:55:29542}
543
[email protected]dd98f392013-02-04 13:03:22544void MetricsService::OnUserAction(const std::string& action) {
[email protected]4426d2d2014-04-09 12:33:00545 log_manager_.current_log()->RecordUserAction(action);
[email protected]dd98f392013-02-04 13:03:22546 HandleIdleSinceLastTransmission(false);
547}
548
ishermanb6705682015-08-29 00:01:00549void MetricsService::FinishedInitTask() {
[email protected]ed0fd002012-04-25 23:10:34550 DCHECK_EQ(INIT_TASK_SCHEDULED, state_);
[email protected]c68a2b9b2013-10-09 18:16:36551 state_ = INIT_TASK_DONE;
[email protected]83d09f92014-06-03 14:58:26552
553 // Create the initial log.
554 if (!initial_metrics_log_.get()) {
555 initial_metrics_log_ = CreateLog(MetricsLog::ONGOING_LOG);
Steven Holtec35411dc2017-07-28 04:22:14556 delegating_provider_.OnDidCreateMetricsLog();
[email protected]83d09f92014-06-03 14:58:26557 }
558
holtec1b97312017-02-24 21:37:10559 rotation_scheduler_->InitTaskComplete();
[email protected]c68a2b9b2013-10-09 18:16:36560}
561
[email protected]076961c2014-03-12 22:23:56562void MetricsService::GetUptimes(PrefService* pref,
563 base::TimeDelta* incremental_uptime,
564 base::TimeDelta* uptime) {
[email protected]c68a2b9b2013-10-09 18:16:36565 base::TimeTicks now = base::TimeTicks::Now();
[email protected]076961c2014-03-12 22:23:56566 // If this is the first call, init |first_updated_time_| and
567 // |last_updated_time_|.
568 if (last_updated_time_.is_null()) {
569 first_updated_time_ = now;
[email protected]c68a2b9b2013-10-09 18:16:36570 last_updated_time_ = now;
[email protected]076961c2014-03-12 22:23:56571 }
572 *incremental_uptime = now - last_updated_time_;
573 *uptime = now - first_updated_time_;
[email protected]c68a2b9b2013-10-09 18:16:36574 last_updated_time_ = now;
575
avi26062922015-12-26 00:14:18576 const int64_t incremental_time_secs = incremental_uptime->InSeconds();
[email protected]c68a2b9b2013-10-09 18:16:36577 if (incremental_time_secs > 0) {
avi26062922015-12-26 00:14:18578 int64_t metrics_uptime = pref->GetInt64(prefs::kUninstallMetricsUptimeSec);
[email protected]c68a2b9b2013-10-09 18:16:36579 metrics_uptime += incremental_time_secs;
asvitkinea63d19e2014-10-24 16:19:39580 pref->SetInt64(prefs::kUninstallMetricsUptimeSec, metrics_uptime);
[email protected]c68a2b9b2013-10-09 18:16:36581 }
initial.commit09911bf2008-07-26 23:55:29582}
583
initial.commit09911bf2008-07-26 23:55:29584//------------------------------------------------------------------------------
585// Recording control methods
586
[email protected]410938e02012-10-24 16:33:59587void MetricsService::OpenNewLog() {
588 DCHECK(!log_manager_.current_log());
initial.commit09911bf2008-07-26 23:55:29589
[email protected]bfb77b52014-06-07 01:54:01590 log_manager_.BeginLoggingWithLog(CreateLog(MetricsLog::ONGOING_LOG));
Steven Holtec35411dc2017-07-28 04:22:14591 delegating_provider_.OnDidCreateMetricsLog();
initial.commit09911bf2008-07-26 23:55:29592 if (state_ == INITIALIZED) {
593 // We only need to schedule that run once.
[email protected]85ed9d42010-06-08 22:37:44594 state_ = INIT_TASK_SCHEDULED;
initial.commit09911bf2008-07-26 23:55:29595
Steven Holte971b0592017-10-12 15:28:26596 base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
597 FROM_HERE,
598 base::Bind(&MetricsService::StartInitTask,
599 self_ptr_factory_.GetWeakPtr()),
[email protected]7e560102012-03-08 20:58:42600 base::TimeDelta::FromSeconds(kInitializationDelaySeconds));
bcwhite8e72aa592017-06-09 18:59:18601
Steven Holte971b0592017-10-12 15:28:26602 base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
bcwhite8e72aa592017-06-09 18:59:18603 FROM_HERE,
604 base::Bind(&MetricsService::PrepareProviderMetricsTask,
605 self_ptr_factory_.GetWeakPtr()),
606 base::TimeDelta::FromSeconds(2 * kInitializationDelaySeconds));
initial.commit09911bf2008-07-26 23:55:29607 }
initial.commit09911bf2008-07-26 23:55:29608}
609
ishermanb6705682015-08-29 00:01:00610void MetricsService::StartInitTask() {
Steven Holtec35411dc2017-07-28 04:22:14611 delegating_provider_.AsyncInit(base::Bind(&MetricsService::FinishedInitTask,
Steven Holte915c99f2017-07-21 23:34:31612 self_ptr_factory_.GetWeakPtr()));
[email protected]51994b22014-05-30 13:24:21613}
614
[email protected]410938e02012-10-24 16:33:59615void MetricsService::CloseCurrentLog() {
[email protected]cac267c2011-09-29 15:18:10616 if (!log_manager_.current_log())
initial.commit09911bf2008-07-26 23:55:29617 return;
618
bcwhite5cb99eb2016-02-01 21:07:56619 // If a persistent allocator is in use, update its internal histograms (such
620 // as how much memory is being used) before reporting.
bcwhite33d95806a2016-03-16 02:37:45621 base::PersistentHistogramAllocator* allocator =
bcwhite5e748c62016-04-06 02:03:53622 base::GlobalHistogramAllocator::Get();
bcwhite5cb99eb2016-02-01 21:07:56623 if (allocator)
624 allocator->UpdateTrackingHistograms();
625
[email protected]0b33f80b2008-12-17 21:34:36626 // Put incremental data (histogram deltas, and realtime stats deltas) at the
[email protected]147bbc0b2009-01-06 19:37:40627 // end of all log transmissions (initial log handles this separately).
[email protected]024b5cd2011-05-27 03:29:38628 // RecordIncrementalStabilityElements only exists on the derived
629 // MetricsLog class.
[email protected]94dce122014-07-16 04:20:12630 MetricsLog* current_log = log_manager_.current_log();
[email protected]024b5cd2011-05-27 03:29:38631 DCHECK(current_log);
asvitkine88aa9332014-09-29 23:29:17632 RecordCurrentEnvironment(current_log);
[email protected]076961c2014-03-12 22:23:56633 base::TimeDelta incremental_uptime;
634 base::TimeDelta uptime;
[email protected]24f81ca2014-05-26 15:59:34635 GetUptimes(local_state_, &incremental_uptime, &uptime);
Steven Holtec35411dc2017-07-28 04:22:14636 current_log->RecordCurrentSessionData(&delegating_provider_,
637 incremental_uptime, uptime);
mariakhomenko191028982014-10-20 23:22:56638 RecordCurrentHistograms();
rkaplow78985a02017-06-05 16:13:19639 current_log->TruncateEvents();
holte6e36a3d2017-02-02 22:41:10640 DVLOG(1) << "Generated an ongoing log.";
holtea3b24112017-03-14 02:08:24641 log_manager_.FinishCurrentLog(log_store());
initial.commit09911bf2008-07-26 23:55:29642}
643
[email protected]cac267c2011-09-29 15:18:10644void MetricsService::PushPendingLogsToPersistentStorage() {
Steven Holte2c294a32015-03-12 21:45:03645 if (state_ < SENDING_LOGS)
[email protected]28ab7f92009-01-06 21:39:04646 return; // We didn't and still don't have time to get plugin list etc.
initial.commit09911bf2008-07-26 23:55:29647
[email protected]410938e02012-10-24 16:33:59648 CloseCurrentLog();
holtea3b24112017-03-14 02:08:24649 log_store()->PersistUnsentLogs();
initial.commit09911bf2008-07-26 23:55:29650}
651
652//------------------------------------------------------------------------------
653// Transmission of logs methods
654
[email protected]7f7f1962011-04-20 15:58:16655void MetricsService::StartSchedulerIfNecessary() {
[email protected]410938e02012-10-24 16:33:59656 // Never schedule cutting or uploading of logs in test mode.
657 if (test_mode_active_)
658 return;
659
660 // Even if reporting is disabled, the scheduler is needed to trigger the
661 // creation of the initial log, which must be done in order for any logs to be
662 // persisted on shutdown or backgrounding.
[email protected]80a8f312013-12-16 18:00:30663 if (recording_active() &&
Steven Holte2c294a32015-03-12 21:45:03664 (reporting_active() || state_ < SENDING_LOGS)) {
holtec1b97312017-02-24 21:37:10665 rotation_scheduler_->Start();
holtea3b24112017-03-14 02:08:24666 reporting_service_.Start();
[email protected]80a8f312013-12-16 18:00:30667 }
initial.commit09911bf2008-07-26 23:55:29668}
669
[email protected]7f7f1962011-04-20 15:58:16670void MetricsService::StartScheduledUpload() {
holte6e36a3d2017-02-02 22:41:10671 DVLOG(1) << "StartScheduledUpload";
holtea6a39172015-03-25 19:57:20672 DCHECK(state_ >= INIT_TASK_DONE);
Brian White8050710b2017-08-30 13:58:04673
[email protected]cd1ac712012-06-26 08:26:47674 // If we're getting no notifications, then the log won't have much in it, and
675 // it's possible the computer is about to go to sleep, so don't upload and
676 // stop the scheduler.
[email protected]410938e02012-10-24 16:33:59677 // If recording has been turned off, the scheduler doesn't need to run.
678 // If reporting is off, proceed if the initial log hasn't been created, since
679 // that has to happen in order for logs to be cut and stored when persisting.
[email protected]d7ea39e2014-05-22 03:59:18680 // TODO(stuartmorgan): Call Stop() on the scheduler when reporting and/or
[email protected]cd1ac712012-06-26 08:26:47681 // recording are turned off instead of letting it fire and then aborting.
682 if (idle_since_last_transmission_ ||
[email protected]410938e02012-10-24 16:33:59683 !recording_active() ||
Steven Holte2c294a32015-03-12 21:45:03684 (!reporting_active() && state_ >= SENDING_LOGS)) {
holtec1b97312017-02-24 21:37:10685 rotation_scheduler_->Stop();
686 rotation_scheduler_->RotationFinished();
[email protected]7f7f1962011-04-20 15:58:16687 return;
688 }
689
[email protected]cd1ac712012-06-26 08:26:47690 // If there are unsent logs, send the next one. If not, start the asynchronous
691 // process of finalizing the current log for upload.
holtea3b24112017-03-14 02:08:24692 if (state_ == SENDING_LOGS && has_unsent_logs()) {
693 reporting_service_.Start();
holtec1b97312017-02-24 21:37:10694 rotation_scheduler_->RotationFinished();
[email protected]cd1ac712012-06-26 08:26:47695 } else {
holtea6a39172015-03-25 19:57:20696 // There are no logs left to send, so start creating a new one.
ishermanb6705682015-08-29 00:01:00697 client_->CollectFinalMetricsForLog(
[email protected]4b4892b2014-05-22 15:06:15698 base::Bind(&MetricsService::OnFinalLogInfoCollectionDone,
699 self_ptr_factory_.GetWeakPtr()));
[email protected]cd1ac712012-06-26 08:26:47700 }
[email protected]29948262012-03-01 12:15:08701}
702
[email protected]29948262012-03-01 12:15:08703void MetricsService::OnFinalLogInfoCollectionDone() {
holte6e36a3d2017-02-02 22:41:10704 DVLOG(1) << "OnFinalLogInfoCollectionDone";
Brian White8050710b2017-08-30 13:58:04705
[email protected]cd1ac712012-06-26 08:26:47706 // Abort if metrics were turned off during the final info gathering.
[email protected]410938e02012-10-24 16:33:59707 if (!recording_active()) {
holtec1b97312017-02-24 21:37:10708 rotation_scheduler_->Stop();
709 rotation_scheduler_->RotationFinished();
[email protected]d01b8732008-10-16 02:18:07710 return;
711 }
712
holtea6a39172015-03-25 19:57:20713 if (state_ == INIT_TASK_DONE) {
714 PrepareInitialMetricsLog();
715 } else {
716 DCHECK_EQ(SENDING_LOGS, state_);
717 CloseCurrentLog();
718 OpenNewLog();
719 }
holtea3b24112017-03-14 02:08:24720 reporting_service_.Start();
holtec1b97312017-02-24 21:37:10721 rotation_scheduler_->RotationFinished();
holtea3b24112017-03-14 02:08:24722 HandleIdleSinceLastTransmission(true);
[email protected]29948262012-03-01 12:15:08723}
724
manzagopea99d1952016-09-08 23:40:05725bool MetricsService::PrepareInitialStabilityLog(
726 const std::string& prefs_previous_version) {
[email protected]80a8f312013-12-16 18:00:30727 DCHECK_EQ(INITIALIZED, state_);
[email protected]29948262012-03-01 12:15:08728
dchengd99c42a2016-04-21 21:54:13729 std::unique_ptr<MetricsLog> initial_stability_log(
[email protected]09dee82d2014-05-22 14:00:53730 CreateLog(MetricsLog::INITIAL_STABILITY_LOG));
[email protected]2a321de32014-05-10 19:59:06731
Steven Holtec35411dc2017-07-28 04:22:14732 // Do not call OnDidCreateMetricsLog here because the stability
[email protected]2a321de32014-05-10 19:59:06733 // log describes stats from the _previous_ session.
manzagopea99d1952016-09-08 23:40:05734 std::string system_profile_app_version;
735 if (!initial_stability_log->LoadSavedEnvironmentFromPrefs(
Steven Holted0429a702017-08-03 08:56:17736 local_state_, &system_profile_app_version)) {
Steven Holte2c294a32015-03-12 21:45:03737 return false;
manzagopea99d1952016-09-08 23:40:05738 }
739 if (system_profile_app_version != prefs_previous_version)
holte1bf273c2017-02-23 00:22:28740 StabilityMetricsProvider(local_state_).LogStabilityVersionMismatch();
[email protected]85791b0b2014-05-20 15:18:58741
[email protected]80a8f312013-12-16 18:00:30742 log_manager_.PauseCurrentLog();
dcheng51606352015-12-26 21:16:23743 log_manager_.BeginLoggingWithLog(std::move(initial_stability_log));
[email protected]85791b0b2014-05-20 15:18:58744
745 // Note: Some stability providers may record stability stats via histograms,
746 // so this call has to be after BeginLoggingWithLog().
Steven Holtec35411dc2017-07-28 04:22:14747 log_manager_.current_log()->RecordPreviousSessionData(&delegating_provider_);
[email protected]c778687a2014-02-11 14:46:45748 RecordCurrentStabilityHistograms();
[email protected]85791b0b2014-05-20 15:18:58749
holte6e36a3d2017-02-02 22:41:10750 DVLOG(1) << "Generated an stability log.";
holtea3b24112017-03-14 02:08:24751 log_manager_.FinishCurrentLog(log_store());
[email protected]80a8f312013-12-16 18:00:30752 log_manager_.ResumePausedLog();
753
754 // Store unsent logs, including the stability log that was just saved, so
755 // that they're not lost in case of a crash before upload time.
holtea3b24112017-03-14 02:08:24756 log_store()->PersistUnsentLogs();
[email protected]80a8f312013-12-16 18:00:30757
Steven Holte2c294a32015-03-12 21:45:03758 return true;
[email protected]80a8f312013-12-16 18:00:30759}
760
[email protected]b58b8b22014-04-08 22:40:33761void MetricsService::PrepareInitialMetricsLog() {
Steven Holte2c294a32015-03-12 21:45:03762 DCHECK_EQ(INIT_TASK_DONE, state_);
[email protected]0edf8762013-11-21 18:33:30763
asvitkine88aa9332014-09-29 23:29:17764 RecordCurrentEnvironment(initial_metrics_log_.get());
[email protected]076961c2014-03-12 22:23:56765 base::TimeDelta incremental_uptime;
766 base::TimeDelta uptime;
[email protected]24f81ca2014-05-26 15:59:34767 GetUptimes(local_state_, &incremental_uptime, &uptime);
[email protected]29948262012-03-01 12:15:08768
769 // Histograms only get written to the current log, so make the new log current
770 // before writing them.
771 log_manager_.PauseCurrentLog();
dcheng51606352015-12-26 21:16:23772 log_manager_.BeginLoggingWithLog(std::move(initial_metrics_log_));
[email protected]85791b0b2014-05-20 15:18:58773
774 // Note: Some stability providers may record stability stats via histograms,
775 // so this call has to be after BeginLoggingWithLog().
Steven Holte631803df2017-07-24 23:40:34776 log_manager_.current_log()->RecordCurrentSessionData(
Steven Holtec35411dc2017-07-28 04:22:14777 &delegating_provider_, base::TimeDelta(), base::TimeDelta());
mariakhomenko191028982014-10-20 23:22:56778 RecordCurrentHistograms();
[email protected]85791b0b2014-05-20 15:18:58779
holte6e36a3d2017-02-02 22:41:10780 DVLOG(1) << "Generated an initial log.";
holtea3b24112017-03-14 02:08:24781 log_manager_.FinishCurrentLog(log_store());
[email protected]29948262012-03-01 12:15:08782 log_manager_.ResumePausedLog();
783
[email protected]94dce122014-07-16 04:20:12784 // Store unsent logs, including the initial log that was just saved, so
785 // that they're not lost in case of a crash before upload time.
holtea3b24112017-03-14 02:08:24786 log_store()->PersistUnsentLogs();
holtea6a39172015-03-25 19:57:20787
788 state_ = SENDING_LOGS;
[email protected]29948262012-03-01 12:15:08789}
790
[email protected]57ecc4b2010-08-11 03:02:51791void MetricsService::IncrementLongPrefsValue(const char* path) {
avi26062922015-12-26 00:14:18792 int64_t value = local_state_->GetInt64(path);
[email protected]24f81ca2014-05-26 15:59:34793 local_state_->SetInt64(path, value + 1);
[email protected]0bb1a622009-03-04 03:22:32794}
795
[email protected]c0c55e92011-09-10 18:47:30796bool MetricsService::UmaMetricsProperlyShutdown() {
797 CHECK(clean_shutdown_status_ == CLEANLY_SHUTDOWN ||
798 clean_shutdown_status_ == NEED_TO_SHUTDOWN);
799 return clean_shutdown_status_ == CLEANLY_SHUTDOWN;
800}
801
[email protected]85791b0b2014-05-20 15:18:58802void MetricsService::RegisterMetricsProvider(
dchengd99c42a2016-04-21 21:54:13803 std::unique_ptr<MetricsProvider> provider) {
[email protected]85791b0b2014-05-20 15:18:58804 DCHECK_EQ(INITIALIZED, state_);
Steven Holtec35411dc2017-07-28 04:22:14805 delegating_provider_.RegisterMetricsProvider(std::move(provider));
[email protected]85791b0b2014-05-20 15:18:58806}
807
Gabriel Charette45f796f2017-07-12 07:00:54808void MetricsService::CheckForClonedInstall() {
809 state_manager_->CheckForClonedInstall();
[email protected]99c892d2014-03-24 18:11:21810}
811
dchengd99c42a2016-04-21 21:54:13812std::unique_ptr<MetricsLog> MetricsService::CreateLog(
813 MetricsLog::LogType log_type) {
ricea85ec57952016-08-31 09:34:10814 return base::MakeUnique<MetricsLog>(state_manager_->client_id(), session_id_,
Steven Holted0429a702017-08-03 08:56:17815 log_type, client_);
816}
817
818std::string MetricsService::RecordCurrentEnvironmentHelper(
819 MetricsLog* log,
820 PrefService* local_state,
Steven Holte8e9db0ca2017-08-11 01:20:08821 DelegatingProvider* delegating_provider) {
Steven Holted0429a702017-08-03 08:56:17822 const SystemProfileProto& system_profile =
Steven Holte8e9db0ca2017-08-11 01:20:08823 log->RecordEnvironment(delegating_provider);
Steven Holted0429a702017-08-03 08:56:17824 EnvironmentRecorder recorder(local_state);
825 return recorder.SerializeAndRecordEnvironmentToPrefs(system_profile);
[email protected]09dee82d2014-05-22 14:00:53826}
827
asvitkine88aa9332014-09-29 23:29:17828void MetricsService::RecordCurrentEnvironment(MetricsLog* log) {
manzagopa5d6688d2016-10-25 20:16:03829 DCHECK(client_);
Steven Holte8e9db0ca2017-08-11 01:20:08830 std::string serialized_proto =
831 RecordCurrentEnvironmentHelper(log, local_state_, &delegating_provider_);
Steven Holted0429a702017-08-03 08:56:17832 GlobalPersistentSystemProfile::GetInstance()->SetSystemProfile(
833 serialized_proto, /*complete=*/true);
834 client_->OnEnvironmentUpdate(&serialized_proto);
asvitkine88aa9332014-09-29 23:29:17835}
836
[email protected]acc2ce5512014-05-22 18:29:13837void MetricsService::RecordCurrentHistograms() {
838 DCHECK(log_manager_.current_log());
bcwhite9556e8172016-06-10 19:55:04839 SCOPED_UMA_HISTOGRAM_TIMER("UMA.MetricsService.RecordCurrentHistograms.Time");
bcwhite05dc0922016-06-03 04:59:44840
Alexei Svitkine24a116bb2017-07-24 18:31:31841 // "true" indicates that StatisticsRecorder should include histograms held in
842 // persistent storage.
843 base::StatisticsRecorder::PrepareDeltas(
844 true, base::Histogram::kNoFlags,
845 base::Histogram::kUmaTargetedHistogramFlag, &histogram_snapshot_manager_);
Steven Holtec35411dc2017-07-28 04:22:14846 delegating_provider_.RecordHistogramSnapshots(&histogram_snapshot_manager_);
[email protected]acc2ce5512014-05-22 18:29:13847}
848
849void MetricsService::RecordCurrentStabilityHistograms() {
850 DCHECK(log_manager_.current_log());
Alexei Svitkine24a116bb2017-07-24 18:31:31851 // "true" indicates that StatisticsRecorder should include histograms held in
bcwhite5cb99eb2016-02-01 21:07:56852 // persistent storage.
Alexei Svitkine24a116bb2017-07-24 18:31:31853 base::StatisticsRecorder::PrepareDeltas(
854 true, base::Histogram::kNoFlags,
855 base::Histogram::kUmaStabilityHistogramFlag,
856 &histogram_snapshot_manager_);
Steven Holtec35411dc2017-07-28 04:22:14857 delegating_provider_.RecordInitialHistogramSnapshots(
858 &histogram_snapshot_manager_);
[email protected]acc2ce5512014-05-22 18:29:13859}
860
bcwhite8e72aa592017-06-09 18:59:18861bool MetricsService::PrepareProviderMetricsLog() {
Steven Holte971b0592017-10-12 15:28:26862 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bcwhite8e72aa592017-06-09 18:59:18863
864 // Create a new log. This will have some defaut values injected in it but
865 // those will be overwritten when an embedded profile is extracted.
866 std::unique_ptr<MetricsLog> log = CreateLog(MetricsLog::INDEPENDENT_LOG);
867
Steven Holtec35411dc2017-07-28 04:22:14868 for (auto& provider : delegating_provider_.GetProviders()) {
bcwhite8e72aa592017-06-09 18:59:18869 if (log->LoadIndependentMetrics(provider.get())) {
870 log_manager_.PauseCurrentLog();
871 log_manager_.BeginLoggingWithLog(std::move(log));
872 log_manager_.FinishCurrentLog(log_store());
873 log_manager_.ResumePausedLog();
874 return true;
875 }
876 }
877 return false;
878}
879
880void MetricsService::PrepareProviderMetricsTask() {
Steven Holte971b0592017-10-12 15:28:26881 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bcwhite8e72aa592017-06-09 18:59:18882 bool found = PrepareProviderMetricsLog();
883 base::TimeDelta next_check = found ? base::TimeDelta::FromSeconds(5)
884 : base::TimeDelta::FromMinutes(15);
Steven Holte971b0592017-10-12 15:28:26885 base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
bcwhite8e72aa592017-06-09 18:59:18886 FROM_HERE,
887 base::Bind(&MetricsService::PrepareProviderMetricsTask,
888 self_ptr_factory_.GetWeakPtr()),
889 next_check);
890}
891
holte6d341162016-12-19 21:42:42892void MetricsService::LogCleanShutdown(bool end_completed) {
Steven Holte971b0592017-10-12 15:28:26893 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]c0c55e92011-09-10 18:47:30894 // Redundant setting to assure that we always reset this value at shutdown
895 // (and that we don't use some alternate path, and not call LogCleanShutdown).
896 clean_shutdown_status_ = CLEANLY_SHUTDOWN;
manzagop14aff5d2016-11-23 17:27:00897 client_->OnLogCleanShutdown();
Ilya Sherman6c6c8332017-07-11 22:39:22898 state_manager_->clean_exit_beacon()->WriteBeaconValue(true);
holtea27eadf2017-01-26 01:58:59899 SetExecutionPhase(ExecutionPhase::SHUTDOWN_COMPLETE, local_state_);
holte1bf273c2017-02-23 00:22:28900 StabilityMetricsProvider(local_state_).MarkSessionEndCompleted(end_completed);
initial.commit09911bf2008-07-26 23:55:29901}
asvitkinecbd420732014-08-26 22:15:40902
903} // namespace metrics