blob: 86e07d95cd02176fbe4a7f0d26ddccf7df41eedc [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"
[email protected]acc2ce5512014-05-22 18:29:13135#include "base/metrics/histogram_base.h"
Ilya Sherman1edb6f182017-12-12 04:00:42136#include "base/metrics/histogram_functions.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]567d30e2012-07-13 21:48:29140#include "base/metrics/statistics_recorder.h"
skyostilb0daa012015-06-02 19:03:48141#include "base/single_thread_task_runner.h"
Robert Kaplowd45b6202017-07-20 02:01:46142#include "base/strings/string_piece.h"
Steven Holte971b0592017-10-12 15:28:26143#include "base/threading/sequenced_task_runner_handle.h"
[email protected]64b8652c2014-07-16 19:14:28144#include "base/time/time.h"
avi26062922015-12-26 00:14:18145#include "build/build_config.h"
holte1bf273c2017-02-23 00:22:28146#include "components/metrics/environment_recorder.h"
Steven Holte5c6dd632017-07-19 23:25:49147#include "components/metrics/field_trials_provider.h"
[email protected]91b1d912014-06-05 10:52:08148#include "components/metrics/metrics_log.h"
[email protected]064107e2014-05-02 00:59:06149#include "components/metrics/metrics_log_manager.h"
[email protected]0d5a61a82014-05-31 22:28:34150#include "components/metrics/metrics_log_uploader.h"
[email protected]7f07db62014-05-15 01:12:45151#include "components/metrics/metrics_pref_names.h"
holte68395852017-01-10 20:40:21152#include "components/metrics/metrics_rotation_scheduler.h"
[email protected]73929422014-05-22 08:19:05153#include "components/metrics/metrics_service_client.h"
[email protected]16a30912014-06-04 00:20:04154#include "components/metrics/metrics_state_manager.h"
Steven Holted0429a702017-08-03 08:56:17155#include "components/metrics/persistent_system_profile.h"
holte1bf273c2017-02-23 00:22:28156#include "components/metrics/stability_metrics_provider.h"
holte567a16f22017-01-06 01:53:45157#include "components/metrics/url_constants.h"
brettwf00b9b42016-02-01 22:11:38158#include "components/prefs/pref_registry_simple.h"
159#include "components/prefs/pref_service.h"
[email protected]50ae9f12013-08-29 18:03:22160#include "components/variations/entropy_provider.h"
initial.commit09911bf2008-07-26 23:55:29161
asvitkinecbd420732014-08-26 22:15:40162namespace metrics {
[email protected]e1acf6f2008-10-27 20:43:33163
holte6e36a3d2017-02-02 22:41:10164namespace {
165
[email protected]7f7f1962011-04-20 15:58:16166// The delay, in seconds, after starting recording before doing expensive
167// initialization work.
[email protected]12180f82012-10-10 21:13:30168#if defined(OS_ANDROID) || defined(OS_IOS)
169// On mobile devices, a significant portion of sessions last less than a minute.
170// Use a shorter timer on these platforms to avoid losing data.
171// TODO(dfalcantara): To avoid delaying startup, tighten up initialization so
172// that it occurs after the user gets their initial page.
173const int kInitializationDelaySeconds = 5;
174#else
[email protected]fe58acc22012-02-29 01:29:58175const int kInitializationDelaySeconds = 30;
[email protected]12180f82012-10-10 21:13:30176#endif
[email protected]252873ef2008-08-04 21:59:45177
Sigurdur Asgeirsson57952502018-01-29 16:15:08178// The browser last live timestamp is updated every 15 minutes.
179const int kUpdateAliveTimestampSeconds = 15 * 60;
180
hashimotoa5c00e28d2015-03-27 06:28:37181#if defined(OS_ANDROID) || defined(OS_IOS)
erikwright65b58df2014-09-12 00:05:28182void MarkAppCleanShutdownAndCommit(CleanExitBeacon* clean_exit_beacon,
183 PrefService* local_state) {
184 clean_exit_beacon->WriteBeaconValue(true);
[email protected]84c384e2013-03-01 23:20:19185 // Start writing right away (write happens on a different thread).
[email protected]24f81ca2014-05-26 15:59:34186 local_state->CommitPendingWrite();
[email protected]84c384e2013-03-01 23:20:19187}
hashimotoa5c00e28d2015-03-27 06:28:37188#endif // defined(OS_ANDROID) || defined(OS_IOS)
[email protected]84c384e2013-03-01 23:20:19189
[email protected]20f999b52012-08-24 22:32:59190} // namespace
initial.commit09911bf2008-07-26 23:55:29191
[email protected]c0c55e92011-09-10 18:47:30192// static
193MetricsService::ShutdownCleanliness MetricsService::clean_shutdown_status_ =
194 MetricsService::CLEANLY_SHUTDOWN;
195
initial.commit09911bf2008-07-26 23:55:29196// static
[email protected]b1de2c72013-02-06 02:45:47197void MetricsService::RegisterPrefs(PrefRegistrySimple* registry) {
holte1bf273c2017-02-23 00:22:28198 CleanExitBeacon::RegisterPrefs(registry);
asvitkinea63d19e2014-10-24 16:19:39199 MetricsStateManager::RegisterPrefs(registry);
[email protected]91b1d912014-06-05 10:52:08200 MetricsLog::RegisterPrefs(registry);
holte1bf273c2017-02-23 00:22:28201 StabilityMetricsProvider::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),
Jeremy Roman5c341f6d2019-07-15 15:56:10222 session_id_(-1) {
Steven Holte971b0592017-10-12 15:28:26223 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]39076642014-05-05 20:32:55224 DCHECK(state_manager_);
[email protected]728de072014-05-21 09:20:32225 DCHECK(client_);
[email protected]24f81ca2014-05-26 15:59:34226 DCHECK(local_state_);
[email protected]64b8652c2014-07-16 19:14:28227
Steven Holte5c6dd632017-07-19 23:25:49228 RegisterMetricsProvider(
Gyuyoung Kim6afb5082018-01-19 13:35:57229 std::make_unique<StabilityMetricsProvider>(local_state_));
Steven Holte5c6dd632017-07-19 23:25:49230
Steven Holted0429a702017-08-03 08:56:17231 RegisterMetricsProvider(state_manager_->GetProvider());
232
Gyuyoung Kim6afb5082018-01-19 13:35:57233 RegisterMetricsProvider(std::make_unique<variations::FieldTrialsProvider>(
Robert Kaplowd45b6202017-07-20 02:01:46234 &synthetic_trial_registry_, base::StringPiece()));
initial.commit09911bf2008-07-26 23:55:29235}
236
237MetricsService::~MetricsService() {
[email protected]410938e02012-10-24 16:33:59238 DisableRecording();
initial.commit09911bf2008-07-26 23:55:29239}
240
[email protected]39076642014-05-05 20:32:55241void MetricsService::InitializeMetricsRecordingState() {
holtea3b24112017-03-14 02:08:24242 reporting_service_.Initialize();
[email protected]39076642014-05-05 20:32:55243 InitializeMetricsState();
[email protected]80a8f312013-12-16 18:00:30244
gayaned52ca402015-02-23 21:23:06245 base::Closure upload_callback =
246 base::Bind(&MetricsService::StartScheduledUpload,
247 self_ptr_factory_.GetWeakPtr());
holte68395852017-01-10 20:40:21248
holtec1b97312017-02-24 21:37:10249 rotation_scheduler_.reset(new MetricsRotationScheduler(
250 upload_callback,
251 // MetricsServiceClient outlives MetricsService, and
252 // MetricsRotationScheduler is tied to the lifetime of |this|.
Nate Fischer5764f2f2019-09-13 23:00:02253 base::Bind(&MetricsServiceClient::GetUploadInterval,
Nate Fischere8236432019-10-25 02:36:32254 base::Unretained(client_)),
255 client_->ShouldStartUpFastForTesting()));
dhsharpb0073a22016-02-18 21:54:09256
Ran Jib5891ad2018-03-21 23:12:16257 // Init() has to be called after LogCrash() in order for LogCrash() to work.
Steven Holtec35411dc2017-07-28 04:22:14258 delegating_provider_.Init();
[email protected]80a8f312013-12-16 18:00:30259}
260
[email protected]d01b8732008-10-16 02:18:07261void MetricsService::Start() {
[email protected]b1c8dc02011-04-13 18:32:04262 HandleIdleSinceLastTransmission(false);
[email protected]410938e02012-10-24 16:33:59263 EnableRecording();
264 EnableReporting();
[email protected]d01b8732008-10-16 02:18:07265}
266
[email protected]410938e02012-10-24 16:33:59267void MetricsService::StartRecordingForTests() {
268 test_mode_active_ = true;
269 EnableRecording();
270 DisableReporting();
[email protected]d01b8732008-10-16 02:18:07271}
272
Sigurdur Asgeirsson57952502018-01-29 16:15:08273void MetricsService::StartUpdatingLastLiveTimestamp() {
274 base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
275 FROM_HERE,
276 base::BindOnce(&MetricsService::UpdateLastLiveTimestampTask,
277 self_ptr_factory_.GetWeakPtr()),
278 base::TimeDelta::FromSeconds(kUpdateAliveTimestampSeconds));
279}
280
[email protected]d01b8732008-10-16 02:18:07281void MetricsService::Stop() {
[email protected]b1c8dc02011-04-13 18:32:04282 HandleIdleSinceLastTransmission(false);
[email protected]410938e02012-10-24 16:33:59283 DisableReporting();
284 DisableRecording();
285}
286
287void MetricsService::EnableReporting() {
holtea3b24112017-03-14 02:08:24288 if (reporting_service_.reporting_active())
[email protected]410938e02012-10-24 16:33:59289 return;
holtea3b24112017-03-14 02:08:24290 reporting_service_.EnableReporting();
[email protected]410938e02012-10-24 16:33:59291 StartSchedulerIfNecessary();
292}
293
294void MetricsService::DisableReporting() {
holtea3b24112017-03-14 02:08:24295 reporting_service_.DisableReporting();
[email protected]d01b8732008-10-16 02:18:07296}
297
[email protected]edafd4c2011-05-10 17:18:53298std::string MetricsService::GetClientId() {
[email protected]39076642014-05-05 20:32:55299 return state_manager_->client_id();
[email protected]edafd4c2011-05-10 17:18:53300}
301
avi26062922015-12-26 00:14:18302int64_t MetricsService::GetInstallDate() {
Steven Holte8e9db0ca2017-08-11 01:20:08303 return state_manager_->GetInstallDate();
olivierrobinc3dfc5b2015-04-07 19:12:00304}
305
drogerb8d286e42015-07-08 09:07:09306bool MetricsService::WasLastShutdownClean() const {
Ilya Sherman6c6c8332017-07-11 22:39:22307 return state_manager_->clean_exit_beacon()->exited_cleanly();
drogerb8d286e42015-07-08 09:07:09308}
309
[email protected]410938e02012-10-24 16:33:59310void MetricsService::EnableRecording() {
Steven Holte971b0592017-10-12 15:28:26311 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
initial.commit09911bf2008-07-26 23:55:29312
wittman622851e2015-07-31 18:13:40313 if (recording_state_ == ACTIVE)
initial.commit09911bf2008-07-26 23:55:29314 return;
wittman622851e2015-07-31 18:13:40315 recording_state_ = ACTIVE;
initial.commit09911bf2008-07-26 23:55:29316
[email protected]39076642014-05-05 20:32:55317 state_manager_->ForceClientIdCreation();
[email protected]9d1b0152014-07-09 18:53:22318 client_->SetMetricsClientId(state_manager_->client_id());
Steven Holted0429a702017-08-03 08:56:17319
[email protected]410938e02012-10-24 16:33:59320 if (!log_manager_.current_log())
321 OpenNewLog();
[email protected]005ef3e2009-05-22 20:55:46322
Steven Holtec35411dc2017-07-28 04:22:14323 delegating_provider_.OnRecordingEnabled();
[email protected]85791b0b2014-05-20 15:18:58324
Alexei Svitkine70c95022019-08-21 18:13:24325 // Fill in the system profile in the log and persist it (to prefs, .pma and
326 // crashpad). This includes running the providers so that information like
327 // field trials and hardware info is provided. If Chrome crashes before this
328 // log is completed, the .pma file will have this system profile.
329 RecordCurrentEnvironment(log_manager_.current_log(), /*complete=*/false);
330
[email protected]e6e30ac2014-01-13 21:24:39331 base::RemoveActionCallback(action_callback_);
[email protected]dd98f392013-02-04 13:03:22332 action_callback_ = base::Bind(&MetricsService::OnUserAction,
333 base::Unretained(this));
[email protected]e6e30ac2014-01-13 21:24:39334 base::AddActionCallback(action_callback_);
[email protected]410938e02012-10-24 16:33:59335}
336
337void MetricsService::DisableRecording() {
Steven Holte971b0592017-10-12 15:28:26338 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]410938e02012-10-24 16:33:59339
wittman622851e2015-07-31 18:13:40340 if (recording_state_ == INACTIVE)
[email protected]410938e02012-10-24 16:33:59341 return;
wittman622851e2015-07-31 18:13:40342 recording_state_ = INACTIVE;
[email protected]410938e02012-10-24 16:33:59343
[email protected]e6e30ac2014-01-13 21:24:39344 base::RemoveActionCallback(action_callback_);
[email protected]85791b0b2014-05-20 15:18:58345
Steven Holtec35411dc2017-07-28 04:22:14346 delegating_provider_.OnRecordingDisabled();
[email protected]85791b0b2014-05-20 15:18:58347
[email protected]410938e02012-10-24 16:33:59348 PushPendingLogsToPersistentStorage();
initial.commit09911bf2008-07-26 23:55:29349}
350
[email protected]d01b8732008-10-16 02:18:07351bool MetricsService::recording_active() const {
Steven Holte971b0592017-10-12 15:28:26352 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
wittman622851e2015-07-31 18:13:40353 return recording_state_ == ACTIVE;
initial.commit09911bf2008-07-26 23:55:29354}
355
[email protected]d01b8732008-10-16 02:18:07356bool MetricsService::reporting_active() const {
Steven Holte971b0592017-10-12 15:28:26357 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
holtea3b24112017-03-14 02:08:24358 return reporting_service_.reporting_active();
359}
360
361bool MetricsService::has_unsent_logs() const {
362 return reporting_service_.metrics_log_store()->has_unsent_logs();
initial.commit09911bf2008-07-26 23:55:29363}
364
[email protected]acc2ce5512014-05-22 18:29:13365void MetricsService::RecordDelta(const base::HistogramBase& histogram,
366 const base::HistogramSamples& snapshot) {
367 log_manager_.current_log()->RecordHistogramDelta(histogram.histogram_name(),
368 snapshot);
369}
370
[email protected]d01b8732008-10-16 02:18:07371void MetricsService::HandleIdleSinceLastTransmission(bool in_idle) {
372 // If there wasn't a lot of action, maybe the computer was asleep, in which
373 // case, the log transmissions should have stopped. Here we start them up
374 // again.
[email protected]cac78842008-11-27 01:02:20375 if (!in_idle && idle_since_last_transmission_)
[email protected]7f7f1962011-04-20 15:58:16376 StartSchedulerIfNecessary();
[email protected]cac78842008-11-27 01:02:20377 idle_since_last_transmission_ = in_idle;
initial.commit09911bf2008-07-26 23:55:29378}
379
[email protected]d7ea39e2014-05-22 03:59:18380void MetricsService::OnApplicationNotIdle() {
wittman622851e2015-07-31 18:13:40381 if (recording_state_ == ACTIVE)
[email protected]d7ea39e2014-05-22 03:59:18382 HandleIdleSinceLastTransmission(false);
383}
384
initial.commit09911bf2008-07-26 23:55:29385void MetricsService::RecordStartOfSessionEnd() {
holte6d341162016-12-19 21:42:42386 LogCleanShutdown(false);
initial.commit09911bf2008-07-26 23:55:29387}
388
389void MetricsService::RecordCompletedSessionEnd() {
holte6d341162016-12-19 21:42:42390 LogCleanShutdown(true);
initial.commit09911bf2008-07-26 23:55:29391}
392
[email protected]410938e02012-10-24 16:33:59393#if defined(OS_ANDROID) || defined(OS_IOS)
Dan Harrington1d9c1102019-05-09 17:21:12394void MetricsService::OnAppEnterBackground(bool keep_recording_in_background) {
395 if (!keep_recording_in_background) {
396 rotation_scheduler_->Stop();
397 reporting_service_.Stop();
398 }
[email protected]117fbdf22012-06-26 18:36:39399
Ilya Sherman6c6c8332017-07-11 22:39:22400 MarkAppCleanShutdownAndCommit(state_manager_->clean_exit_beacon(),
401 local_state_);
[email protected]117fbdf22012-06-26 18:36:39402
bmcquade6a49bed2016-07-27 19:25:56403 // Give providers a chance to persist histograms as part of being
404 // backgrounded.
Steven Holtec35411dc2017-07-28 04:22:14405 delegating_provider_.OnAppEnterBackground();
bmcquade6a49bed2016-07-27 19:25:56406
[email protected]117fbdf22012-06-26 18:36:39407 // At this point, there's no way of knowing when the process will be
408 // killed, so this has to be treated similar to a shutdown, closing and
409 // persisting all logs. Unlinke a shutdown, the state is primed to be ready
410 // to continue logging and uploading if the process does return.
Steven Holte2c294a32015-03-12 21:45:03411 if (recording_active() && state_ >= SENDING_LOGS) {
[email protected]117fbdf22012-06-26 18:36:39412 PushPendingLogsToPersistentStorage();
[email protected]410938e02012-10-24 16:33:59413 // Persisting logs closes the current log, so start recording a new log
414 // immediately to capture any background work that might be done before the
415 // process is killed.
416 OpenNewLog();
[email protected]117fbdf22012-06-26 18:36:39417 }
[email protected]117fbdf22012-06-26 18:36:39418}
419
Dan Harrington5b7dfc12019-08-21 18:14:30420void MetricsService::OnAppEnterForeground(bool force_open_new_log) {
Ilya Sherman6c6c8332017-07-11 22:39:22421 state_manager_->clean_exit_beacon()->WriteBeaconValue(false);
[email protected]117fbdf22012-06-26 18:36:39422 StartSchedulerIfNecessary();
Dan Harrington5b7dfc12019-08-21 18:14:30423
424 if (force_open_new_log && recording_active() && state_ >= SENDING_LOGS) {
425 // Because state_ >= SENDING_LOGS, PushPendingLogsToPersistentStorage()
426 // will close the log, allowing a new log to be opened.
427 PushPendingLogsToPersistentStorage();
428 OpenNewLog();
429 }
[email protected]117fbdf22012-06-26 18:36:39430}
Dan Harrington5b7dfc12019-08-21 18:14:30431
[email protected]84c384e2013-03-01 23:20:19432#else
erikwrightcc98a7e02014-09-09 22:05:12433void MetricsService::LogNeedForCleanShutdown() {
Ilya Sherman6c6c8332017-07-11 22:39:22434 state_manager_->clean_exit_beacon()->WriteBeaconValue(false);
[email protected]84c384e2013-03-01 23:20:19435 // Redundant setting to be sure we call for a clean shutdown.
436 clean_shutdown_status_ = NEED_TO_SHUTDOWN;
437}
438#endif // defined(OS_ANDROID) || defined(OS_IOS)
[email protected]117fbdf22012-06-26 18:36:39439
[email protected]7f7f1962011-04-20 15:58:16440void MetricsService::RecordBreakpadRegistration(bool success) {
holte1bf273c2017-02-23 00:22:28441 StabilityMetricsProvider(local_state_).RecordBreakpadRegistration(success);
[email protected]e73c01972008-08-13 00:18:24442}
443
444void MetricsService::RecordBreakpadHasDebugger(bool has_debugger) {
holte1bf273c2017-02-23 00:22:28445 StabilityMetricsProvider(local_state_)
446 .RecordBreakpadHasDebugger(has_debugger);
[email protected]e73c01972008-08-13 00:18:24447}
448
yiyaoliu14ef3ead2014-11-19 02:36:50449void MetricsService::ClearSavedStabilityMetrics() {
Steven Holtec35411dc2017-07-28 04:22:14450 delegating_provider_.ClearSavedStabilityMetrics();
yiyaoliu14ef3ead2014-11-19 02:36:50451}
452
olivierrobinc3dfc5b2015-04-07 19:12:00453void MetricsService::PushExternalLog(const std::string& log) {
holtea3b24112017-03-14 02:08:24454 log_store()->StoreLog(log, MetricsLog::ONGOING_LOG);
olivierrobinc3dfc5b2015-04-07 19:12:00455}
456
initial.commit09911bf2008-07-26 23:55:29457//------------------------------------------------------------------------------
458// private methods
459//------------------------------------------------------------------------------
460
461
462//------------------------------------------------------------------------------
463// Initialization methods
464
[email protected]39076642014-05-05 20:32:55465void MetricsService::InitializeMetricsState() {
avi26062922015-12-26 00:14:18466 const int64_t buildtime = MetricsLog::GetBuildTime();
asvitkineff3e2a62014-09-18 22:01:49467 const std::string version = client_->GetVersionString();
holte57fcaed2017-01-23 22:14:31468
asvitkineff3e2a62014-09-18 22:01:49469 bool version_changed = false;
holte1bf273c2017-02-23 00:22:28470 EnvironmentRecorder recorder(local_state_);
471 int64_t previous_buildtime = recorder.GetLastBuildtime();
472 std::string previous_version = recorder.GetLastVersion();
manzagopea99d1952016-09-08 23:40:05473 if (previous_buildtime != buildtime || previous_version != version) {
holte1bf273c2017-02-23 00:22:28474 recorder.SetBuildtimeAndVersion(buildtime, version);
asvitkineff3e2a62014-09-18 22:01:49475 version_changed = true;
476 }
initial.commit09911bf2008-07-26 23:55:29477
asvitkinea63d19e2014-10-24 16:19:39478 session_id_ = local_state_->GetInteger(prefs::kMetricsSessionID);
erikwright65b58df2014-09-12 00:05:28479
holte1bf273c2017-02-23 00:22:28480 StabilityMetricsProvider provider(local_state_);
Ilya Sherman6c6c8332017-07-11 22:39:22481 if (!state_manager_->clean_exit_beacon()->exited_cleanly()) {
Sigurdur Asgeirsson8c67a592018-02-02 21:10:33482 provider.LogCrash(
483 state_manager_->clean_exit_beacon()->browser_last_live_timestamp());
[email protected]c0c55e92011-09-10 18:47:30484 // Reset flag, and wait until we call LogNeedForCleanShutdown() before
485 // monitoring.
Ilya Sherman6c6c8332017-07-11 22:39:22486 state_manager_->clean_exit_beacon()->WriteBeaconValue(true);
siggic179dd062014-09-10 17:02:31487 }
[email protected]6a6d0d12013-10-28 15:58:19488
Steven Holtec35411dc2017-07-28 04:22:14489 // HasPreviousSessionData is called first to ensure it is never bypassed.
manzagop780bb8b2016-10-21 14:21:16490 const bool is_initial_stability_log_required =
Steven Holtec35411dc2017-07-28 04:22:14491 delegating_provider_.HasPreviousSessionData() ||
Ilya Sherman6c6c8332017-07-11 22:39:22492 !state_manager_->clean_exit_beacon()->exited_cleanly();
Steven Holte2c294a32015-03-12 21:45:03493 bool has_initial_stability_log = false;
manzagop780bb8b2016-10-21 14:21:16494 if (is_initial_stability_log_required) {
siggic179dd062014-09-10 17:02:31495 // If the previous session didn't exit cleanly, or if any provider
496 // explicitly requests it, prepare an initial stability log -
497 // provided UMA is enabled.
manzagopea99d1952016-09-08 23:40:05498 if (state_manager_->IsMetricsReportingEnabled()) {
499 has_initial_stability_log = PrepareInitialStabilityLog(previous_version);
500 if (!has_initial_stability_log)
holte1bf273c2017-02-23 00:22:28501 provider.LogStabilityLogDeferred();
manzagopea99d1952016-09-08 23:40:05502 }
initial.commit09911bf2008-07-26 23:55:29503 }
[email protected]80a8f312013-12-16 18:00:30504
manzagop780bb8b2016-10-21 14:21:16505 // If the version changed, but no initial stability log was generated, clear
506 // the stability stats from the previous version (so that they don't get
asvitkineff3e2a62014-09-18 22:01:49507 // attributed to the current version). This could otherwise happen due to a
508 // number of different edge cases, such as if the last version crashed before
509 // it could save off a system profile or if UMA reporting is disabled (which
510 // normally results in stats being accumulated).
manzagop780bb8b2016-10-21 14:21:16511 if (version_changed && !has_initial_stability_log) {
yiyaoliu14ef3ead2014-11-19 02:36:50512 ClearSavedStabilityMetrics();
holte1bf273c2017-02-23 00:22:28513 provider.LogStabilityDataDiscarded();
manzagopea99d1952016-09-08 23:40:05514 }
asvitkineff3e2a62014-09-18 22:01:49515
manzagop780bb8b2016-10-21 14:21:16516 // If the version changed, the system profile is obsolete and needs to be
517 // cleared. This is to avoid the stability data misattribution that could
518 // occur if the current version crashed before saving its own system profile.
519 // Note however this clearing occurs only after preparing the initial
520 // stability log, an operation that requires the previous version's system
521 // profile. At this point, stability metrics pertaining to the previous
522 // version have been cleared.
holte1bf273c2017-02-23 00:22:28523 if (version_changed)
524 recorder.ClearEnvironmentFromPrefs();
manzagop780bb8b2016-10-21 14:21:16525
[email protected]80a8f312013-12-16 18:00:30526 // Update session ID.
527 ++session_id_;
asvitkinea63d19e2014-10-24 16:19:39528 local_state_->SetInteger(prefs::kMetricsSessionID, session_id_);
[email protected]80a8f312013-12-16 18:00:30529
holte1bf273c2017-02-23 00:22:28530 // Notify stability metrics providers about the launch.
531 provider.LogLaunch();
holte1bf273c2017-02-23 00:22:28532 provider.CheckLastSessionEndCompleted();
initial.commit09911bf2008-07-26 23:55:29533
[email protected]076961c2014-03-12 22:23:56534 // Call GetUptimes() for the first time, thus allowing all later calls
535 // to record incremental uptimes accurately.
536 base::TimeDelta ignored_uptime_parameter;
537 base::TimeDelta startup_uptime;
[email protected]24f81ca2014-05-26 15:59:34538 GetUptimes(local_state_, &startup_uptime, &ignored_uptime_parameter);
[email protected]c68a2b9b2013-10-09 18:16:36539 DCHECK_EQ(0, startup_uptime.InMicroseconds());
[email protected]0bb1a622009-03-04 03:22:32540
541 // Bookkeeping for the uninstall metrics.
asvitkinea63d19e2014-10-24 16:19:39542 IncrementLongPrefsValue(prefs::kUninstallLaunchCount);
initial.commit09911bf2008-07-26 23:55:29543}
544
[email protected]dd98f392013-02-04 13:03:22545void MetricsService::OnUserAction(const std::string& action) {
[email protected]4426d2d2014-04-09 12:33:00546 log_manager_.current_log()->RecordUserAction(action);
[email protected]dd98f392013-02-04 13:03:22547 HandleIdleSinceLastTransmission(false);
548}
549
ishermanb6705682015-08-29 00:01:00550void MetricsService::FinishedInitTask() {
[email protected]ed0fd002012-04-25 23:10:34551 DCHECK_EQ(INIT_TASK_SCHEDULED, state_);
[email protected]c68a2b9b2013-10-09 18:16:36552 state_ = INIT_TASK_DONE;
[email protected]83d09f92014-06-03 14:58:26553
554 // Create the initial log.
Zinovy Nis3c5a779e2018-05-11 07:09:50555 if (!initial_metrics_log_) {
[email protected]83d09f92014-06-03 14:58:26556 initial_metrics_log_ = CreateLog(MetricsLog::ONGOING_LOG);
Steven Holtec35411dc2017-07-28 04:22:14557 delegating_provider_.OnDidCreateMetricsLog();
[email protected]83d09f92014-06-03 14:58:26558 }
559
holtec1b97312017-02-24 21:37:10560 rotation_scheduler_->InitTaskComplete();
[email protected]c68a2b9b2013-10-09 18:16:36561}
562
[email protected]076961c2014-03-12 22:23:56563void MetricsService::GetUptimes(PrefService* pref,
564 base::TimeDelta* incremental_uptime,
565 base::TimeDelta* uptime) {
[email protected]c68a2b9b2013-10-09 18:16:36566 base::TimeTicks now = base::TimeTicks::Now();
[email protected]076961c2014-03-12 22:23:56567 // If this is the first call, init |first_updated_time_| and
568 // |last_updated_time_|.
569 if (last_updated_time_.is_null()) {
570 first_updated_time_ = now;
[email protected]c68a2b9b2013-10-09 18:16:36571 last_updated_time_ = now;
[email protected]076961c2014-03-12 22:23:56572 }
573 *incremental_uptime = now - last_updated_time_;
574 *uptime = now - first_updated_time_;
[email protected]c68a2b9b2013-10-09 18:16:36575 last_updated_time_ = now;
576
avi26062922015-12-26 00:14:18577 const int64_t incremental_time_secs = incremental_uptime->InSeconds();
[email protected]c68a2b9b2013-10-09 18:16:36578 if (incremental_time_secs > 0) {
avi26062922015-12-26 00:14:18579 int64_t metrics_uptime = pref->GetInt64(prefs::kUninstallMetricsUptimeSec);
[email protected]c68a2b9b2013-10-09 18:16:36580 metrics_uptime += incremental_time_secs;
asvitkinea63d19e2014-10-24 16:19:39581 pref->SetInt64(prefs::kUninstallMetricsUptimeSec, metrics_uptime);
[email protected]c68a2b9b2013-10-09 18:16:36582 }
initial.commit09911bf2008-07-26 23:55:29583}
584
initial.commit09911bf2008-07-26 23:55:29585//------------------------------------------------------------------------------
586// Recording control methods
587
[email protected]410938e02012-10-24 16:33:59588void MetricsService::OpenNewLog() {
589 DCHECK(!log_manager_.current_log());
initial.commit09911bf2008-07-26 23:55:29590
[email protected]bfb77b52014-06-07 01:54:01591 log_manager_.BeginLoggingWithLog(CreateLog(MetricsLog::ONGOING_LOG));
Steven Holtec35411dc2017-07-28 04:22:14592 delegating_provider_.OnDidCreateMetricsLog();
initial.commit09911bf2008-07-26 23:55:29593 if (state_ == INITIALIZED) {
594 // We only need to schedule that run once.
[email protected]85ed9d42010-06-08 22:37:44595 state_ = INIT_TASK_SCHEDULED;
initial.commit09911bf2008-07-26 23:55:29596
Nate Fischere8236432019-10-25 02:36:32597 base::TimeDelta initialization_delay = base::TimeDelta::FromSeconds(
598 client_->ShouldStartUpFastForTesting() ? 0
599 : kInitializationDelaySeconds);
Steven Holte971b0592017-10-12 15:28:26600 base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
601 FROM_HERE,
tzik2bcf8e42018-07-31 11:22:15602 base::BindOnce(&MetricsService::StartInitTask,
603 self_ptr_factory_.GetWeakPtr()),
Nate Fischere8236432019-10-25 02:36:32604 initialization_delay);
bcwhite8e72aa592017-06-09 18:59:18605
Steven Holte971b0592017-10-12 15:28:26606 base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
bcwhite8e72aa592017-06-09 18:59:18607 FROM_HERE,
tzik2bcf8e42018-07-31 11:22:15608 base::BindOnce(&MetricsService::PrepareProviderMetricsTask,
609 self_ptr_factory_.GetWeakPtr()),
Nate Fischere8236432019-10-25 02:36:32610 2 * initialization_delay);
initial.commit09911bf2008-07-26 23:55:29611 }
612}
613
ishermanb6705682015-08-29 00:01:00614void MetricsService::StartInitTask() {
Steven Holtec35411dc2017-07-28 04:22:14615 delegating_provider_.AsyncInit(base::Bind(&MetricsService::FinishedInitTask,
Steven Holte915c99f2017-07-21 23:34:31616 self_ptr_factory_.GetWeakPtr()));
[email protected]51994b22014-05-30 13:24:21617}
618
[email protected]410938e02012-10-24 16:33:59619void MetricsService::CloseCurrentLog() {
[email protected]cac267c2011-09-29 15:18:10620 if (!log_manager_.current_log())
initial.commit09911bf2008-07-26 23:55:29621 return;
622
bcwhite5cb99eb2016-02-01 21:07:56623 // If a persistent allocator is in use, update its internal histograms (such
624 // as how much memory is being used) before reporting.
bcwhite33d95806a2016-03-16 02:37:45625 base::PersistentHistogramAllocator* allocator =
bcwhite5e748c62016-04-06 02:03:53626 base::GlobalHistogramAllocator::Get();
bcwhite5cb99eb2016-02-01 21:07:56627 if (allocator)
628 allocator->UpdateTrackingHistograms();
629
[email protected]0b33f80b2008-12-17 21:34:36630 // Put incremental data (histogram deltas, and realtime stats deltas) at the
[email protected]147bbc0b2009-01-06 19:37:40631 // end of all log transmissions (initial log handles this separately).
[email protected]024b5cd2011-05-27 03:29:38632 // RecordIncrementalStabilityElements only exists on the derived
633 // MetricsLog class.
[email protected]94dce122014-07-16 04:20:12634 MetricsLog* current_log = log_manager_.current_log();
[email protected]024b5cd2011-05-27 03:29:38635 DCHECK(current_log);
Alexei Svitkine70c95022019-08-21 18:13:24636 RecordCurrentEnvironment(current_log, /*complete=*/true);
[email protected]076961c2014-03-12 22:23:56637 base::TimeDelta incremental_uptime;
638 base::TimeDelta uptime;
[email protected]24f81ca2014-05-26 15:59:34639 GetUptimes(local_state_, &incremental_uptime, &uptime);
Steven Holtec35411dc2017-07-28 04:22:14640 current_log->RecordCurrentSessionData(&delegating_provider_,
641 incremental_uptime, uptime);
mariakhomenko191028982014-10-20 23:22:56642 RecordCurrentHistograms();
rkaplow78985a02017-06-05 16:13:19643 current_log->TruncateEvents();
holte6e36a3d2017-02-02 22:41:10644 DVLOG(1) << "Generated an ongoing log.";
holtea3b24112017-03-14 02:08:24645 log_manager_.FinishCurrentLog(log_store());
initial.commit09911bf2008-07-26 23:55:29646}
647
[email protected]cac267c2011-09-29 15:18:10648void MetricsService::PushPendingLogsToPersistentStorage() {
Steven Holte2c294a32015-03-12 21:45:03649 if (state_ < SENDING_LOGS)
[email protected]28ab7f92009-01-06 21:39:04650 return; // We didn't and still don't have time to get plugin list etc.
initial.commit09911bf2008-07-26 23:55:29651
[email protected]410938e02012-10-24 16:33:59652 CloseCurrentLog();
holtea3b24112017-03-14 02:08:24653 log_store()->PersistUnsentLogs();
initial.commit09911bf2008-07-26 23:55:29654}
655
656//------------------------------------------------------------------------------
657// Transmission of logs methods
658
[email protected]7f7f1962011-04-20 15:58:16659void MetricsService::StartSchedulerIfNecessary() {
[email protected]410938e02012-10-24 16:33:59660 // Never schedule cutting or uploading of logs in test mode.
661 if (test_mode_active_)
662 return;
663
664 // Even if reporting is disabled, the scheduler is needed to trigger the
665 // creation of the initial log, which must be done in order for any logs to be
666 // persisted on shutdown or backgrounding.
[email protected]80a8f312013-12-16 18:00:30667 if (recording_active() &&
Steven Holte2c294a32015-03-12 21:45:03668 (reporting_active() || state_ < SENDING_LOGS)) {
holtec1b97312017-02-24 21:37:10669 rotation_scheduler_->Start();
holtea3b24112017-03-14 02:08:24670 reporting_service_.Start();
[email protected]80a8f312013-12-16 18:00:30671 }
initial.commit09911bf2008-07-26 23:55:29672}
673
[email protected]7f7f1962011-04-20 15:58:16674void MetricsService::StartScheduledUpload() {
holte6e36a3d2017-02-02 22:41:10675 DVLOG(1) << "StartScheduledUpload";
holtea6a39172015-03-25 19:57:20676 DCHECK(state_ >= INIT_TASK_DONE);
Brian White8050710b2017-08-30 13:58:04677
[email protected]cd1ac712012-06-26 08:26:47678 // If we're getting no notifications, then the log won't have much in it, and
679 // it's possible the computer is about to go to sleep, so don't upload and
680 // stop the scheduler.
[email protected]410938e02012-10-24 16:33:59681 // If recording has been turned off, the scheduler doesn't need to run.
682 // If reporting is off, proceed if the initial log hasn't been created, since
683 // that has to happen in order for logs to be cut and stored when persisting.
[email protected]d7ea39e2014-05-22 03:59:18684 // TODO(stuartmorgan): Call Stop() on the scheduler when reporting and/or
[email protected]cd1ac712012-06-26 08:26:47685 // recording are turned off instead of letting it fire and then aborting.
686 if (idle_since_last_transmission_ ||
[email protected]410938e02012-10-24 16:33:59687 !recording_active() ||
Steven Holte2c294a32015-03-12 21:45:03688 (!reporting_active() && state_ >= SENDING_LOGS)) {
holtec1b97312017-02-24 21:37:10689 rotation_scheduler_->Stop();
690 rotation_scheduler_->RotationFinished();
[email protected]7f7f1962011-04-20 15:58:16691 return;
692 }
693
[email protected]cd1ac712012-06-26 08:26:47694 // If there are unsent logs, send the next one. If not, start the asynchronous
695 // process of finalizing the current log for upload.
holtea3b24112017-03-14 02:08:24696 if (state_ == SENDING_LOGS && has_unsent_logs()) {
697 reporting_service_.Start();
holtec1b97312017-02-24 21:37:10698 rotation_scheduler_->RotationFinished();
[email protected]cd1ac712012-06-26 08:26:47699 } else {
holtea6a39172015-03-25 19:57:20700 // There are no logs left to send, so start creating a new one.
ishermanb6705682015-08-29 00:01:00701 client_->CollectFinalMetricsForLog(
[email protected]4b4892b2014-05-22 15:06:15702 base::Bind(&MetricsService::OnFinalLogInfoCollectionDone,
703 self_ptr_factory_.GetWeakPtr()));
[email protected]cd1ac712012-06-26 08:26:47704 }
[email protected]29948262012-03-01 12:15:08705}
706
[email protected]29948262012-03-01 12:15:08707void MetricsService::OnFinalLogInfoCollectionDone() {
holte6e36a3d2017-02-02 22:41:10708 DVLOG(1) << "OnFinalLogInfoCollectionDone";
Brian White8050710b2017-08-30 13:58:04709
[email protected]cd1ac712012-06-26 08:26:47710 // Abort if metrics were turned off during the final info gathering.
[email protected]410938e02012-10-24 16:33:59711 if (!recording_active()) {
holtec1b97312017-02-24 21:37:10712 rotation_scheduler_->Stop();
713 rotation_scheduler_->RotationFinished();
[email protected]d01b8732008-10-16 02:18:07714 return;
715 }
716
holtea6a39172015-03-25 19:57:20717 if (state_ == INIT_TASK_DONE) {
718 PrepareInitialMetricsLog();
719 } else {
720 DCHECK_EQ(SENDING_LOGS, state_);
721 CloseCurrentLog();
722 OpenNewLog();
723 }
holtea3b24112017-03-14 02:08:24724 reporting_service_.Start();
holtec1b97312017-02-24 21:37:10725 rotation_scheduler_->RotationFinished();
holtea3b24112017-03-14 02:08:24726 HandleIdleSinceLastTransmission(true);
[email protected]29948262012-03-01 12:15:08727}
728
manzagopea99d1952016-09-08 23:40:05729bool MetricsService::PrepareInitialStabilityLog(
730 const std::string& prefs_previous_version) {
[email protected]80a8f312013-12-16 18:00:30731 DCHECK_EQ(INITIALIZED, state_);
[email protected]29948262012-03-01 12:15:08732
dchengd99c42a2016-04-21 21:54:13733 std::unique_ptr<MetricsLog> initial_stability_log(
[email protected]09dee82d2014-05-22 14:00:53734 CreateLog(MetricsLog::INITIAL_STABILITY_LOG));
[email protected]2a321de32014-05-10 19:59:06735
Steven Holtec35411dc2017-07-28 04:22:14736 // Do not call OnDidCreateMetricsLog here because the stability
[email protected]2a321de32014-05-10 19:59:06737 // log describes stats from the _previous_ session.
manzagopea99d1952016-09-08 23:40:05738 std::string system_profile_app_version;
739 if (!initial_stability_log->LoadSavedEnvironmentFromPrefs(
Steven Holted0429a702017-08-03 08:56:17740 local_state_, &system_profile_app_version)) {
Steven Holte2c294a32015-03-12 21:45:03741 return false;
manzagopea99d1952016-09-08 23:40:05742 }
743 if (system_profile_app_version != prefs_previous_version)
holte1bf273c2017-02-23 00:22:28744 StabilityMetricsProvider(local_state_).LogStabilityVersionMismatch();
[email protected]85791b0b2014-05-20 15:18:58745
[email protected]80a8f312013-12-16 18:00:30746 log_manager_.PauseCurrentLog();
dcheng51606352015-12-26 21:16:23747 log_manager_.BeginLoggingWithLog(std::move(initial_stability_log));
[email protected]85791b0b2014-05-20 15:18:58748
749 // Note: Some stability providers may record stability stats via histograms,
750 // so this call has to be after BeginLoggingWithLog().
Steven Holtec35411dc2017-07-28 04:22:14751 log_manager_.current_log()->RecordPreviousSessionData(&delegating_provider_);
[email protected]c778687a2014-02-11 14:46:45752 RecordCurrentStabilityHistograms();
[email protected]85791b0b2014-05-20 15:18:58753
holte6e36a3d2017-02-02 22:41:10754 DVLOG(1) << "Generated an stability log.";
holtea3b24112017-03-14 02:08:24755 log_manager_.FinishCurrentLog(log_store());
[email protected]80a8f312013-12-16 18:00:30756 log_manager_.ResumePausedLog();
757
758 // Store unsent logs, including the stability log that was just saved, so
759 // that they're not lost in case of a crash before upload time.
holtea3b24112017-03-14 02:08:24760 log_store()->PersistUnsentLogs();
[email protected]80a8f312013-12-16 18:00:30761
Steven Holte2c294a32015-03-12 21:45:03762 return true;
[email protected]80a8f312013-12-16 18:00:30763}
764
[email protected]b58b8b22014-04-08 22:40:33765void MetricsService::PrepareInitialMetricsLog() {
Steven Holte2c294a32015-03-12 21:45:03766 DCHECK_EQ(INIT_TASK_DONE, state_);
[email protected]0edf8762013-11-21 18:33:30767
Alexei Svitkine70c95022019-08-21 18:13:24768 RecordCurrentEnvironment(initial_metrics_log_.get(), /*complete=*/true);
[email protected]076961c2014-03-12 22:23:56769 base::TimeDelta incremental_uptime;
770 base::TimeDelta uptime;
[email protected]24f81ca2014-05-26 15:59:34771 GetUptimes(local_state_, &incremental_uptime, &uptime);
[email protected]29948262012-03-01 12:15:08772
773 // Histograms only get written to the current log, so make the new log current
774 // before writing them.
775 log_manager_.PauseCurrentLog();
dcheng51606352015-12-26 21:16:23776 log_manager_.BeginLoggingWithLog(std::move(initial_metrics_log_));
[email protected]85791b0b2014-05-20 15:18:58777
778 // Note: Some stability providers may record stability stats via histograms,
779 // so this call has to be after BeginLoggingWithLog().
Steven Holte631803df2017-07-24 23:40:34780 log_manager_.current_log()->RecordCurrentSessionData(
Steven Holtec35411dc2017-07-28 04:22:14781 &delegating_provider_, base::TimeDelta(), base::TimeDelta());
mariakhomenko191028982014-10-20 23:22:56782 RecordCurrentHistograms();
[email protected]85791b0b2014-05-20 15:18:58783
holte6e36a3d2017-02-02 22:41:10784 DVLOG(1) << "Generated an initial log.";
holtea3b24112017-03-14 02:08:24785 log_manager_.FinishCurrentLog(log_store());
[email protected]29948262012-03-01 12:15:08786 log_manager_.ResumePausedLog();
787
[email protected]94dce122014-07-16 04:20:12788 // Store unsent logs, including the initial log that was just saved, so
789 // that they're not lost in case of a crash before upload time.
holtea3b24112017-03-14 02:08:24790 log_store()->PersistUnsentLogs();
holtea6a39172015-03-25 19:57:20791
792 state_ = SENDING_LOGS;
[email protected]29948262012-03-01 12:15:08793}
794
[email protected]57ecc4b2010-08-11 03:02:51795void MetricsService::IncrementLongPrefsValue(const char* path) {
avi26062922015-12-26 00:14:18796 int64_t value = local_state_->GetInt64(path);
[email protected]24f81ca2014-05-26 15:59:34797 local_state_->SetInt64(path, value + 1);
[email protected]0bb1a622009-03-04 03:22:32798}
799
[email protected]c0c55e92011-09-10 18:47:30800bool MetricsService::UmaMetricsProperlyShutdown() {
801 CHECK(clean_shutdown_status_ == CLEANLY_SHUTDOWN ||
802 clean_shutdown_status_ == NEED_TO_SHUTDOWN);
803 return clean_shutdown_status_ == CLEANLY_SHUTDOWN;
804}
805
[email protected]85791b0b2014-05-20 15:18:58806void MetricsService::RegisterMetricsProvider(
dchengd99c42a2016-04-21 21:54:13807 std::unique_ptr<MetricsProvider> provider) {
[email protected]85791b0b2014-05-20 15:18:58808 DCHECK_EQ(INITIALIZED, state_);
Steven Holtec35411dc2017-07-28 04:22:14809 delegating_provider_.RegisterMetricsProvider(std::move(provider));
[email protected]85791b0b2014-05-20 15:18:58810}
811
Gabriel Charette45f796f2017-07-12 07:00:54812void MetricsService::CheckForClonedInstall() {
813 state_manager_->CheckForClonedInstall();
[email protected]99c892d2014-03-24 18:11:21814}
815
dchengd99c42a2016-04-21 21:54:13816std::unique_ptr<MetricsLog> MetricsService::CreateLog(
817 MetricsLog::LogType log_type) {
Gyuyoung Kim6afb5082018-01-19 13:35:57818 return std::make_unique<MetricsLog>(state_manager_->client_id(), session_id_,
Steven Holted0429a702017-08-03 08:56:17819 log_type, client_);
820}
821
Alexei Svitkine70c95022019-08-21 18:13:24822void MetricsService::SetPersistentSystemProfile(
823 const std::string& serialized_proto,
824 bool complete) {
825 GlobalPersistentSystemProfile::GetInstance()->SetSystemProfile(
826 serialized_proto, complete);
827}
828
829// static
Steven Holted0429a702017-08-03 08:56:17830std::string MetricsService::RecordCurrentEnvironmentHelper(
831 MetricsLog* log,
832 PrefService* local_state,
Steven Holte8e9db0ca2017-08-11 01:20:08833 DelegatingProvider* delegating_provider) {
Steven Holted0429a702017-08-03 08:56:17834 const SystemProfileProto& system_profile =
Steven Holte8e9db0ca2017-08-11 01:20:08835 log->RecordEnvironment(delegating_provider);
Steven Holted0429a702017-08-03 08:56:17836 EnvironmentRecorder recorder(local_state);
837 return recorder.SerializeAndRecordEnvironmentToPrefs(system_profile);
[email protected]09dee82d2014-05-22 14:00:53838}
839
Alexei Svitkine70c95022019-08-21 18:13:24840void MetricsService::RecordCurrentEnvironment(MetricsLog* log, bool complete) {
manzagopa5d6688d2016-10-25 20:16:03841 DCHECK(client_);
Steven Holte8e9db0ca2017-08-11 01:20:08842 std::string serialized_proto =
843 RecordCurrentEnvironmentHelper(log, local_state_, &delegating_provider_);
Alexei Svitkine70c95022019-08-21 18:13:24844
845 SetPersistentSystemProfile(serialized_proto, complete);
Steven Holted0429a702017-08-03 08:56:17846 client_->OnEnvironmentUpdate(&serialized_proto);
asvitkine88aa9332014-09-29 23:29:17847}
848
[email protected]acc2ce5512014-05-22 18:29:13849void MetricsService::RecordCurrentHistograms() {
850 DCHECK(log_manager_.current_log());
bcwhite05dc0922016-06-03 04:59:44851
Alexei Svitkine24a116bb2017-07-24 18:31:31852 // "true" indicates that StatisticsRecorder should include histograms held in
853 // persistent storage.
854 base::StatisticsRecorder::PrepareDeltas(
855 true, base::Histogram::kNoFlags,
856 base::Histogram::kUmaTargetedHistogramFlag, &histogram_snapshot_manager_);
Steven Holtec35411dc2017-07-28 04:22:14857 delegating_provider_.RecordHistogramSnapshots(&histogram_snapshot_manager_);
[email protected]acc2ce5512014-05-22 18:29:13858}
859
860void MetricsService::RecordCurrentStabilityHistograms() {
861 DCHECK(log_manager_.current_log());
Alexei Svitkine24a116bb2017-07-24 18:31:31862 // "true" indicates that StatisticsRecorder should include histograms held in
bcwhite5cb99eb2016-02-01 21:07:56863 // persistent storage.
Alexei Svitkine24a116bb2017-07-24 18:31:31864 base::StatisticsRecorder::PrepareDeltas(
865 true, base::Histogram::kNoFlags,
866 base::Histogram::kUmaStabilityHistogramFlag,
867 &histogram_snapshot_manager_);
Steven Holtec35411dc2017-07-28 04:22:14868 delegating_provider_.RecordInitialHistogramSnapshots(
869 &histogram_snapshot_manager_);
[email protected]acc2ce5512014-05-22 18:29:13870}
871
Brian White2868e612018-10-26 01:30:24872void MetricsService::PrepareProviderMetricsLogDone(
873 std::unique_ptr<MetricsLog::IndependentMetricsLoader> loader,
874 bool success) {
875 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
876 DCHECK(independent_loader_active_);
877 DCHECK(loader);
878
879 if (success) {
880 log_manager_.PauseCurrentLog();
881 log_manager_.BeginLoggingWithLog(loader->ReleaseLog());
882 log_manager_.FinishCurrentLog(log_store());
883 log_manager_.ResumePausedLog();
884 }
885
886 independent_loader_active_ = false;
887}
888
bcwhite8e72aa592017-06-09 18:59:18889bool MetricsService::PrepareProviderMetricsLog() {
Steven Holte971b0592017-10-12 15:28:26890 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bcwhite8e72aa592017-06-09 18:59:18891
Brian White2868e612018-10-26 01:30:24892 // If something is still pending, stop now and indicate that there is
893 // still work to do.
894 if (independent_loader_active_)
895 return true;
bcwhite8e72aa592017-06-09 18:59:18896
Brian White2868e612018-10-26 01:30:24897 // Check each provider in turn for data.
Steven Holtec35411dc2017-07-28 04:22:14898 for (auto& provider : delegating_provider_.GetProviders()) {
Brian White2868e612018-10-26 01:30:24899 if (provider->HasIndependentMetrics()) {
900 // Create a new log. This will have some default values injected in it
901 // but those will be overwritten when an embedded profile is extracted.
902 std::unique_ptr<MetricsLog> log = CreateLog(MetricsLog::INDEPENDENT_LOG);
903
Brian Whited384aee2018-10-29 15:41:58904 // Note that something is happening. This must be set before the
905 // operation is requested in case the loader decides to do everything
906 // immediately rather than as a background task.
907 independent_loader_active_ = true;
908
Brian White2868e612018-10-26 01:30:24909 // Give the new log to a loader for management and then run it on the
910 // provider that has something to give. A copy of the pointer is needed
911 // because the unique_ptr may get moved before the value can be used
912 // to call Run().
913 std::unique_ptr<MetricsLog::IndependentMetricsLoader> loader =
914 std::make_unique<MetricsLog::IndependentMetricsLoader>(
915 std::move(log));
916 MetricsLog::IndependentMetricsLoader* loader_ptr = loader.get();
917 loader_ptr->Run(
918 base::BindOnce(&MetricsService::PrepareProviderMetricsLogDone,
919 self_ptr_factory_.GetWeakPtr(), std::move(loader)),
920 provider.get());
Brian White2868e612018-10-26 01:30:24921
922 // Something was found so there may still be more work to do.
bcwhite8e72aa592017-06-09 18:59:18923 return true;
924 }
925 }
Brian White2868e612018-10-26 01:30:24926
927 // Nothing was found so indicate there is no more work to do.
bcwhite8e72aa592017-06-09 18:59:18928 return false;
929}
930
931void MetricsService::PrepareProviderMetricsTask() {
Steven Holte971b0592017-10-12 15:28:26932 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bcwhite8e72aa592017-06-09 18:59:18933 bool found = PrepareProviderMetricsLog();
934 base::TimeDelta next_check = found ? base::TimeDelta::FromSeconds(5)
935 : base::TimeDelta::FromMinutes(15);
Steven Holte971b0592017-10-12 15:28:26936 base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
bcwhite8e72aa592017-06-09 18:59:18937 FROM_HERE,
tzik2bcf8e42018-07-31 11:22:15938 base::BindOnce(&MetricsService::PrepareProviderMetricsTask,
939 self_ptr_factory_.GetWeakPtr()),
bcwhite8e72aa592017-06-09 18:59:18940 next_check);
941}
942
holte6d341162016-12-19 21:42:42943void MetricsService::LogCleanShutdown(bool end_completed) {
Steven Holte971b0592017-10-12 15:28:26944 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]c0c55e92011-09-10 18:47:30945 // Redundant setting to assure that we always reset this value at shutdown
946 // (and that we don't use some alternate path, and not call LogCleanShutdown).
947 clean_shutdown_status_ = CLEANLY_SHUTDOWN;
manzagop14aff5d2016-11-23 17:27:00948 client_->OnLogCleanShutdown();
Ilya Sherman6c6c8332017-07-11 22:39:22949 state_manager_->clean_exit_beacon()->WriteBeaconValue(true);
holte1bf273c2017-02-23 00:22:28950 StabilityMetricsProvider(local_state_).MarkSessionEndCompleted(end_completed);
initial.commit09911bf2008-07-26 23:55:29951}
asvitkinecbd420732014-08-26 22:15:40952
Sigurdur Asgeirsson57952502018-01-29 16:15:08953void MetricsService::UpdateLastLiveTimestampTask() {
954 state_manager_->clean_exit_beacon()->UpdateLastLiveTimestamp();
955
956 // Schecule the next update.
957 StartUpdatingLastLiveTimestamp();
958}
959
asvitkinecbd420732014-08-26 22:15:40960} // namespace metrics