• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 //------------------------------------------------------------------------------
6 // Description of a MetricsService instance's life cycle.
7 //
8 // OVERVIEW
9 //
10 // A MetricsService instance is typically created at application startup.  It is
11 // the central controller for the acquisition of log data, and the automatic
12 // 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,
16 // 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 PrefServices facilities. The retained logs
21 // (the ones that never got transmitted) are compressed and base64-encoded
22 // before being persisted.
23 //
24 // Logs fall into one of two categories: "initial logs," and "ongoing logs."
25 // 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.
33 //
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)
39 // is 30 minutes. That time period starts when the first user action causes a
40 // logging event.  This means that if there is no user action, there may be long
41 // periods without any (ongoing) log transmissions.  Ongoing logs typically
42 // 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
48 // to the UMA server.  The finalization also acquires the most recent number
49 // of page loads, along with any counts of renderer or plugin crashes.
50 //
51 // When the browser shuts down, there will typically be a fragment of an ongoing
52 // 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.
55 //
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
76 // states, based on the State enum specified in the state_ member.  Those states
77 // are:
78 //
79 //  CONSTRUCTED,          // Constructor was called.
80 //  INITIALIZED,          // InitializeMetricsRecordingState() was called.
81 //  INIT_TASK_SCHEDULED,  // Waiting for deferred init tasks to finish.
82 //  INIT_TASK_DONE,       // Waiting for timer to send the first ongoing log.
83 //  SENDING_LOGS,         // Sending logs and creating new ones when we run out.
84 //
85 // In more detail, we have:
86 //
87 //    INIT_TASK_SCHEDULED,    // Waiting for deferred init tasks to finish.
88 // Typically about 30 seconds after startup, a task is sent to a background
89 // thread to perform deferred (lower priority and slower) initialization steps
90 // such as getting the list of plugins.  That task will (when complete) make an
91 // async callback (via a Task) to indicate the completion.
92 //
93 //    INIT_TASK_DONE,         // Waiting for timer to send first ongoing log.
94 // The callback has arrived, and it is now possible for an ongoing log to be
95 // created.  This callback typically arrives back less than one second after
96 // the deferred init task is dispatched.
97 //
98 //    SENDING_LOGS,  // Sending logs and creating new ones when we run out.
99 // Logs from previous sessions have been loaded, and an optional initial
100 // stability log has been created. We will send all of these logs, and when
101 // they run out, we will start cutting new logs to send.  We will also cut a new
102 // log if we expect a shutdown.
103 //
104 // The progression through the above states is simple, and sequential.
105 // States proceed from INITIALIZED to SENDING_LOGS, and remain in the latter
106 // until shutdown.
107 //
108 // Also note that whenever we successfully send a log, we mirror the list
109 // of logs into the PrefService. This ensures that IF we crash, we won't start
110 // up and retransmit our old logs again.
111 //
112 // Due to race conditions, it is always possible that a log file could be sent
113 // twice.  For example, if a log file is sent, but not yet acknowledged by
114 // the external server, and the user shuts down, then a copy of the log may be
115 // saved for re-transmission.  These duplicates could be filtered out server
116 // side, but are not expected to be a significant problem.
117 //
118 //
119 //------------------------------------------------------------------------------
120 
121 #include "components/metrics/metrics_service.h"
122 
123 #include <stddef.h>
124 
125 #include <algorithm>
126 #include <memory>
127 #include <utility>
128 
129 #include "base/callback_list.h"
130 #include "base/functional/bind.h"
131 #include "base/functional/callback.h"
132 #include "base/location.h"
133 #include "base/metrics/histogram_base.h"
134 #include "base/metrics/histogram_flattener.h"
135 #include "base/metrics/histogram_functions.h"
136 #include "base/metrics/histogram_macros.h"
137 #include "base/metrics/histogram_macros_local.h"
138 #include "base/metrics/histogram_samples.h"
139 #include "base/metrics/persistent_histogram_allocator.h"
140 #include "base/metrics/statistics_recorder.h"
141 #include "base/process/process_handle.h"
142 #include "base/rand_util.h"
143 #include "base/strings/string_piece.h"
144 #include "base/task/sequenced_task_runner.h"
145 #include "base/task/single_thread_task_runner.h"
146 #include "base/task/task_traits.h"
147 #include "base/task/thread_pool.h"
148 #include "base/time/time.h"
149 #include "build/build_config.h"
150 #include "build/chromeos_buildflags.h"
151 #include "components/metrics/clean_exit_beacon.h"
152 #include "components/metrics/environment_recorder.h"
153 #include "components/metrics/field_trials_provider.h"
154 #include "components/metrics/metrics_features.h"
155 #include "components/metrics/metrics_log.h"
156 #include "components/metrics/metrics_log_uploader.h"
157 #include "components/metrics/metrics_logs_event_manager.h"
158 #include "components/metrics/metrics_pref_names.h"
159 #include "components/metrics/metrics_rotation_scheduler.h"
160 #include "components/metrics/metrics_service_client.h"
161 #include "components/metrics/metrics_service_observer.h"
162 #include "components/metrics/metrics_state_manager.h"
163 #include "components/metrics/metrics_switches.h"
164 #include "components/metrics/persistent_system_profile.h"
165 #include "components/metrics/stability_metrics_provider.h"
166 #include "components/metrics/url_constants.h"
167 #include "components/prefs/pref_registry_simple.h"
168 #include "components/prefs/pref_service.h"
169 #include "components/variations/entropy_provider.h"
170 
171 #if !BUILDFLAG(IS_ANDROID)
172 #include "components/keep_alive_registry/keep_alive_registry.h"
173 #include "components/keep_alive_registry/keep_alive_types.h"
174 #include "components/keep_alive_registry/scoped_keep_alive.h"
175 #endif  // !BUILDFLAG(IS_ANDROID)
176 
177 namespace metrics {
178 namespace {
179 
180 // Used to write histogram data to a log. Does not take ownership of the log.
181 class IndependentFlattener : public base::HistogramFlattener {
182  public:
IndependentFlattener(MetricsLog * log)183   explicit IndependentFlattener(MetricsLog* log) : log_(log) {}
184 
185   IndependentFlattener(const IndependentFlattener&) = delete;
186   IndependentFlattener& operator=(const IndependentFlattener&) = delete;
187 
188   ~IndependentFlattener() override = default;
189 
190   // base::HistogramFlattener:
RecordDelta(const base::HistogramBase & histogram,const base::HistogramSamples & snapshot)191   void RecordDelta(const base::HistogramBase& histogram,
192                    const base::HistogramSamples& snapshot) override {
193     CHECK(histogram.HasFlags(base::HistogramBase::kUmaTargetedHistogramFlag));
194     log_->RecordHistogramDelta(histogram.histogram_name(), snapshot);
195   }
196 
197  private:
198   const raw_ptr<MetricsLog, AcrossTasksDanglingUntriaged> log_;
199 };
200 
201 // Used to mark histogram samples as reported so that they are not included in
202 // the next log. A histogram's snapshot samples are simply discarded/ignored
203 // when attempting to record them through this |HistogramFlattener|.
204 class DiscardingFlattener : public base::HistogramFlattener {
205  public:
206   DiscardingFlattener() = default;
207 
208   DiscardingFlattener(const DiscardingFlattener&) = delete;
209   DiscardingFlattener& operator=(const DiscardingFlattener&) = delete;
210 
211   ~DiscardingFlattener() override = default;
212 
RecordDelta(const base::HistogramBase & histogram,const base::HistogramSamples & snapshot)213   void RecordDelta(const base::HistogramBase& histogram,
214                    const base::HistogramSamples& snapshot) override {
215     // No-op. We discard the samples.
216   }
217 };
218 
219 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
220 // Emits a histogram upon instantiation, and on destruction. Used to measure how
221 // often the browser is ungracefully killed between two different points. In
222 // particular, currently, this is used on mobile to measure how often the
223 // browser is killed while finalizing a log, right after backgrounding. This
224 // scenario is prone to data loss because a histogram may have been snapshotted
225 // and put into a log, but the browser was killed before it could be fully
226 // finalized and stored.
227 //
228 // TODO(crbug/1293026): Consider improving this. In particular, the "Started"
229 // bucket is emitted before finalizing the log, and the "Finished" bucket is
230 // emitted after. Hence, the latter will be reported in a different log, which
231 // may cause a "lag" and/or bias (e.g. if the latter log is more prone to loss).
232 // A better way to do this is to allocate an object on the persistent memory
233 // upon instantiation, and flip a bit in it upon destruction. A future session
234 // that will consume this persistent memory should take care of emitting the
235 // histogram samples.
236 class ScopedTerminationChecker {
237  public:
238   // These values are persisted to logs. Entries should not be renumbered and
239   // numeric values should never be reused.
240   enum class Status {
241     kStarted = 0,
242     kFinished = 1,
243     kMaxValue = kFinished,
244   };
245 
ScopedTerminationChecker(base::StringPiece histogram_name)246   explicit ScopedTerminationChecker(base::StringPiece histogram_name) {
247     // Do nothing if the persistent histogram system is not being used.
248     // Otherwise, the "Finished" bucket may be more prone to loss, which may
249     // incorrectly make it seem like the browser was killed in between the
250     // scoped code.
251     if (!base::GlobalHistogramAllocator::Get()) {
252       return;
253     }
254 
255     active_ = true;
256     histogram_name_ = histogram_name;
257     base::UmaHistogramEnumeration(histogram_name_, Status::kStarted);
258   }
259 
260   ScopedTerminationChecker(const ScopedTerminationChecker& other) = delete;
261   ScopedTerminationChecker& operator=(const ScopedTerminationChecker& other) =
262       delete;
263 
~ScopedTerminationChecker()264   ~ScopedTerminationChecker() {
265     if (!active_) {
266       return;
267     }
268     base::UmaHistogramEnumeration(histogram_name_, Status::kFinished);
269   }
270 
271  private:
272   // Name of the histogram to emit to upon instantiation/destruction.
273   std::string histogram_name_;
274 
275   // Whether or not this will emit histograms. In particular, if this browser
276   // session does not make use of persistent memory, this will be false, and
277   // this object will do nothing.
278   bool active_ = false;
279 };
280 #endif  // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
281 
282 // The delay, in seconds, after starting recording before doing expensive
283 // initialization work.
284 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
285 // On mobile devices, a significant portion of sessions last less than a minute.
286 // Use a shorter timer on these platforms to avoid losing data.
287 // TODO(dfalcantara): To avoid delaying startup, tighten up initialization so
288 //                    that it occurs after the user gets their initial page.
289 const int kInitializationDelaySeconds = 5;
290 #else
291 const int kInitializationDelaySeconds = 30;
292 #endif
293 
294 // The browser last live timestamp is updated every 15 minutes.
295 const int kUpdateAliveTimestampSeconds = 15 * 60;
296 
297 #if BUILDFLAG(IS_CHROMEOS_ASH)
298 enum UserLogStoreState {
299   kSetPostSendLogsState = 0,
300   kSetPreSendLogsState = 1,
301   kUnsetPostSendLogsState = 2,
302   kUnsetPreSendLogsState = 3,
303   kMaxValue = kUnsetPreSendLogsState,
304 };
305 
RecordUserLogStoreState(UserLogStoreState state)306 void RecordUserLogStoreState(UserLogStoreState state) {
307   base::UmaHistogramEnumeration("UMA.CrosPerUser.UserLogStoreState", state);
308 }
309 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
310 
311 }  // namespace
312 
313 // static
RegisterPrefs(PrefRegistrySimple * registry)314 void MetricsService::RegisterPrefs(PrefRegistrySimple* registry) {
315   CleanExitBeacon::RegisterPrefs(registry);
316   MetricsStateManager::RegisterPrefs(registry);
317   MetricsLog::RegisterPrefs(registry);
318   StabilityMetricsProvider::RegisterPrefs(registry);
319   MetricsReportingService::RegisterPrefs(registry);
320 
321   registry->RegisterIntegerPref(prefs::kMetricsSessionID, -1);
322 }
323 
MetricsService(MetricsStateManager * state_manager,MetricsServiceClient * client,PrefService * local_state)324 MetricsService::MetricsService(MetricsStateManager* state_manager,
325                                MetricsServiceClient* client,
326                                PrefService* local_state)
327     : reporting_service_(client, local_state, &logs_event_manager_),
328       state_manager_(state_manager),
329       client_(client),
330       local_state_(local_state),
331       recording_state_(UNSET),
332       test_mode_active_(false),
333       state_(CONSTRUCTED),
334       idle_since_last_transmission_(false),
335       session_id_(-1) {
336   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
337   DCHECK(state_manager_);
338   DCHECK(client_);
339   DCHECK(local_state_);
340 
341   // Emit a local histogram, which should not be reported to servers. This is
342   // monitored from the serverside.
343   LOCAL_HISTOGRAM_BOOLEAN("UMA.LocalHistogram", true);
344 
345   bool create_logs_event_observer;
346 #ifdef NDEBUG
347   // For non-debug builds, we only create |logs_event_observer_| if the
348   // |kExportUmaLogsToFile| command line flag is passed. This is mostly for
349   // performance reasons: 1) we don't want to have to notify an observer in
350   // non-debug circumstances (there may be heavy work like copying large
351   // strings), and 2) we don't want logs to be lingering in memory.
352   create_logs_event_observer =
353       base::CommandLine::ForCurrentProcess()->HasSwitch(
354           switches::kExportUmaLogsToFile);
355 #else
356   // For debug builds, always create |logs_event_observer_|.
357   create_logs_event_observer = true;
358 #endif  // NDEBUG
359 
360   if (create_logs_event_observer) {
361     logs_event_observer_ = std::make_unique<MetricsServiceObserver>(
362         MetricsServiceObserver::MetricsServiceType::UMA);
363     logs_event_manager_.AddObserver(logs_event_observer_.get());
364   }
365 
366   cloned_install_subscription_ =
367       state_manager->AddOnClonedInstallDetectedCallback(
368           base::BindOnce(&MetricsService::OnClonedInstallDetected,
369                          self_ptr_factory_.GetWeakPtr()));
370 
371   RegisterMetricsProvider(
372       std::make_unique<StabilityMetricsProvider>(local_state_));
373 
374   RegisterMetricsProvider(state_manager_->GetProvider());
375 }
376 
~MetricsService()377 MetricsService::~MetricsService() {
378   DisableRecording();
379 
380   if (logs_event_observer_) {
381     logs_event_manager_.RemoveObserver(logs_event_observer_.get());
382     const base::CommandLine* command_line =
383         base::CommandLine::ForCurrentProcess();
384     if (command_line->HasSwitch(switches::kExportUmaLogsToFile)) {
385       // We should typically not write to files on the main thread, but since
386       // this only happens when |kExportUmaLogsToFile| is passed (which
387       // indicates debugging), this should be fine.
388       logs_event_observer_->ExportLogsToFile(
389           command_line->GetSwitchValuePath(switches::kExportUmaLogsToFile));
390     }
391   }
392 
393   // Emit a local histogram, which should not be reported to servers. This is
394   // monitored from the serverside. Because this is emitted after closing the
395   // last log before shutdown, this sample should be retrieved by the persistent
396   // histograms system in a follow up session. This is to ensure independent
397   // logs do not include local histograms, a previously buggy behaviour.
398   LOCAL_HISTOGRAM_BOOLEAN("UMA.LocalHistogram", true);
399 }
400 
InitializeMetricsRecordingState()401 void MetricsService::InitializeMetricsRecordingState() {
402   DCHECK_EQ(CONSTRUCTED, state_);
403 
404   // The FieldTrialsProvider should be registered last. This ensures that
405   // studies whose features are checked when providers add their information to
406   // the log appear in the active field trials.
407   RegisterMetricsProvider(std::make_unique<variations::FieldTrialsProvider>(
408       client_->GetSyntheticTrialRegistry(), base::StringPiece()));
409 
410   reporting_service_.Initialize();
411   InitializeMetricsState();
412 
413   base::RepeatingClosure upload_callback = base::BindRepeating(
414       &MetricsService::StartScheduledUpload, self_ptr_factory_.GetWeakPtr());
415 
416   rotation_scheduler_ = std::make_unique<MetricsRotationScheduler>(
417       upload_callback,
418       // MetricsServiceClient outlives MetricsService, and
419       // MetricsRotationScheduler is tied to the lifetime of |this|.
420       base::BindRepeating(&MetricsServiceClient::GetUploadInterval,
421                           base::Unretained(client_)),
422       client_->ShouldStartUpFastForTesting());
423 
424   // Init() has to be called after LogCrash() in order for LogCrash() to work.
425   delegating_provider_.Init();
426 
427   state_ = INITIALIZED;
428 }
429 
Start()430 void MetricsService::Start() {
431   HandleIdleSinceLastTransmission(false);
432   EnableRecording();
433   EnableReporting();
434 }
435 
StartRecordingForTests()436 void MetricsService::StartRecordingForTests() {
437   test_mode_active_ = true;
438   EnableRecording();
439   DisableReporting();
440 }
441 
StartUpdatingLastLiveTimestamp()442 void MetricsService::StartUpdatingLastLiveTimestamp() {
443   base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
444       FROM_HERE,
445       base::BindOnce(&MetricsService::UpdateLastLiveTimestampTask,
446                      self_ptr_factory_.GetWeakPtr()),
447       GetUpdateLastAliveTimestampDelay());
448 }
449 
Stop()450 void MetricsService::Stop() {
451   HandleIdleSinceLastTransmission(false);
452   DisableReporting();
453   DisableRecording();
454 }
455 
EnableReporting()456 void MetricsService::EnableReporting() {
457   if (reporting_service_.reporting_active())
458     return;
459   reporting_service_.EnableReporting();
460   StartSchedulerIfNecessary();
461 }
462 
DisableReporting()463 void MetricsService::DisableReporting() {
464   reporting_service_.DisableReporting();
465 }
466 
GetClientId() const467 std::string MetricsService::GetClientId() const {
468   return state_manager_->client_id();
469 }
470 
GetLowEntropySource()471 int MetricsService::GetLowEntropySource() {
472   return state_manager_->GetLowEntropySource();
473 }
474 
GetOldLowEntropySource()475 int MetricsService::GetOldLowEntropySource() {
476   return state_manager_->GetOldLowEntropySource();
477 }
478 
GetPseudoLowEntropySource()479 int MetricsService::GetPseudoLowEntropySource() {
480   return state_manager_->GetPseudoLowEntropySource();
481 }
482 
SetExternalClientId(const std::string & id)483 void MetricsService::SetExternalClientId(const std::string& id) {
484   state_manager_->SetExternalClientId(id);
485 }
486 
WasLastShutdownClean() const487 bool MetricsService::WasLastShutdownClean() const {
488   return state_manager_->clean_exit_beacon()->exited_cleanly();
489 }
490 
EnableRecording()491 void MetricsService::EnableRecording() {
492   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
493 
494   if (recording_state_ == ACTIVE)
495     return;
496   recording_state_ = ACTIVE;
497 
498   state_manager_->ForceClientIdCreation();
499   client_->SetMetricsClientId(state_manager_->client_id());
500 
501   if (!current_log_) {
502     OpenNewLog();
503   }
504 
505   delegating_provider_.OnRecordingEnabled();
506 
507   // Fill in the system profile in the log and persist it (to prefs, .pma
508   // and crashpad). This includes running the providers so that information
509   // like field trials and hardware info is provided. If Chrome crashes
510   // before this log is completed, the .pma file will have this system
511   // profile.
512   RecordCurrentEnvironment(current_log_.get(), /*complete=*/false);
513 
514   base::RemoveActionCallback(action_callback_);
515   action_callback_ = base::BindRepeating(&MetricsService::OnUserAction,
516                                          base::Unretained(this));
517   base::AddActionCallback(action_callback_);
518 
519   enablement_observers_.Notify(/*enabled=*/true);
520 }
521 
DisableRecording()522 void MetricsService::DisableRecording() {
523   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
524 
525   if (recording_state_ == INACTIVE)
526     return;
527   recording_state_ = INACTIVE;
528 
529   base::RemoveActionCallback(action_callback_);
530 
531   delegating_provider_.OnRecordingDisabled();
532 
533   base::UmaHistogramBoolean("UMA.MetricsService.PendingOngoingLogOnDisable",
534                             pending_ongoing_log_);
535   PushPendingLogsToPersistentStorage(
536       MetricsLogsEventManager::CreateReason::kServiceShutdown);
537 
538   // Because histograms may still be emitted after the last log was closed, an
539   // independent log may be created in a future session in order to report
540   // those histograms. To ensure that this independent log contains histograms
541   // that we wish to appear in every log, call OnDidCreateMetricsLog().
542   delegating_provider_.OnDidCreateMetricsLog();
543 
544   enablement_observers_.Notify(/*enabled=*/false);
545 }
546 
recording_active() const547 bool MetricsService::recording_active() const {
548   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
549   return recording_state_ == ACTIVE;
550 }
551 
reporting_active() const552 bool MetricsService::reporting_active() const {
553   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
554   return reporting_service_.reporting_active();
555 }
556 
has_unsent_logs() const557 bool MetricsService::has_unsent_logs() const {
558   return reporting_service_.metrics_log_store()->has_unsent_logs();
559 }
560 
IsMetricsReportingEnabled() const561 bool MetricsService::IsMetricsReportingEnabled() const {
562   return state_manager_->IsMetricsReportingEnabled();
563 }
564 
HandleIdleSinceLastTransmission(bool in_idle)565 void MetricsService::HandleIdleSinceLastTransmission(bool in_idle) {
566   // If there wasn't a lot of action, maybe the computer was asleep, in which
567   // case, the log transmissions should have stopped.  Here we start them up
568   // again.
569   if (!in_idle && idle_since_last_transmission_)
570     StartSchedulerIfNecessary();
571   idle_since_last_transmission_ = in_idle;
572 }
573 
OnApplicationNotIdle()574 void MetricsService::OnApplicationNotIdle() {
575   if (recording_state_ == ACTIVE)
576     HandleIdleSinceLastTransmission(false);
577 }
578 
579 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
OnAppEnterBackground(bool keep_recording_in_background)580 void MetricsService::OnAppEnterBackground(bool keep_recording_in_background) {
581   is_in_foreground_ = false;
582   reporting_service_.SetIsInForegound(false);
583   if (!keep_recording_in_background) {
584     rotation_scheduler_->Stop();
585     reporting_service_.Stop();
586   }
587 
588   state_manager_->LogHasSessionShutdownCleanly(true);
589   // Schedule a write, which happens on a different thread.
590   local_state_->CommitPendingWrite();
591 
592   // Give providers a chance to persist histograms as part of being
593   // backgrounded.
594   delegating_provider_.OnAppEnterBackground();
595 
596   // At this point, there's no way of knowing when the process will be killed,
597   // so this has to be treated similar to a shutdown, closing and persisting all
598   // logs. Unlike a shutdown, the state is primed to be ready to continue
599   // logging and uploading if the process does return.
600   if (recording_active() && !IsTooEarlyToCloseLog()) {
601     base::UmaHistogramBoolean(
602         "UMA.MetricsService.PendingOngoingLogOnBackgrounded",
603         pending_ongoing_log_);
604 #if BUILDFLAG(IS_ANDROID)
605     client_->MergeSubprocessHistograms();
606 #endif  // BUILDFLAG(IS_ANDROID)
607     {
608       ScopedTerminationChecker scoped_termination_checker(
609           "UMA.MetricsService.OnBackgroundedScopedTerminationChecker");
610       PushPendingLogsToPersistentStorage(
611           MetricsLogsEventManager::CreateReason::kBackgrounded);
612     }
613     // Persisting logs closes the current log, so start recording a new log
614     // immediately to capture any background work that might be done before the
615     // process is killed.
616     OpenNewLog();
617   }
618 }
619 
OnAppEnterForeground(bool force_open_new_log)620 void MetricsService::OnAppEnterForeground(bool force_open_new_log) {
621   is_in_foreground_ = true;
622   reporting_service_.SetIsInForegound(true);
623   state_manager_->LogHasSessionShutdownCleanly(false);
624   StartSchedulerIfNecessary();
625 
626   if (force_open_new_log && recording_active() && !IsTooEarlyToCloseLog()) {
627     base::UmaHistogramBoolean(
628         "UMA.MetricsService.PendingOngoingLogOnForegrounded",
629         pending_ongoing_log_);
630 #if BUILDFLAG(IS_ANDROID)
631     client_->MergeSubprocessHistograms();
632 #endif  // BUILDFLAG(IS_ANDROID)
633     // Because state_ >= SENDING_LOGS, PushPendingLogsToPersistentStorage()
634     // will close the log, allowing a new log to be opened.
635     PushPendingLogsToPersistentStorage(
636         MetricsLogsEventManager::CreateReason::kForegrounded);
637     OpenNewLog();
638   }
639 }
640 #endif  // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
641 
OnPageLoadStarted()642 void MetricsService::OnPageLoadStarted() {
643   delegating_provider_.OnPageLoadStarted();
644 }
645 
LogCleanShutdown()646 void MetricsService::LogCleanShutdown() {
647   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
648   state_manager_->LogHasSessionShutdownCleanly(true);
649 }
650 
ClearSavedStabilityMetrics()651 void MetricsService::ClearSavedStabilityMetrics() {
652   delegating_provider_.ClearSavedStabilityMetrics();
653   // Stability metrics are stored in Local State prefs, so schedule a Local
654   // State write to flush the updated prefs.
655   local_state_->CommitPendingWrite();
656 }
657 
MarkCurrentHistogramsAsReported()658 void MetricsService::MarkCurrentHistogramsAsReported() {
659   DiscardingFlattener flattener;
660   base::HistogramSnapshotManager snapshot_manager(&flattener);
661   base::StatisticsRecorder::PrepareDeltas(
662       /*include_persistent=*/true, /*flags_to_set=*/base::Histogram::kNoFlags,
663       /*required_flags=*/base::Histogram::kUmaTargetedHistogramFlag,
664       &snapshot_manager);
665 }
666 
667 #if BUILDFLAG(IS_CHROMEOS_ASH)
SetUserLogStore(std::unique_ptr<UnsentLogStore> user_log_store)668 void MetricsService::SetUserLogStore(
669     std::unique_ptr<UnsentLogStore> user_log_store) {
670   if (log_store()->has_alternate_ongoing_log_store())
671     return;
672 
673   if (state_ >= SENDING_LOGS) {
674     // Closes the current log so that a new log can be opened in the user log
675     // store.
676     PushPendingLogsToPersistentStorage(
677         MetricsLogsEventManager::CreateReason::kAlternateOngoingLogStoreSet);
678     log_store()->SetAlternateOngoingLogStore(std::move(user_log_store));
679     OpenNewLog();
680     RecordUserLogStoreState(kSetPostSendLogsState);
681   } else {
682     // Initial log has not yet been created and flushing now would result in
683     // incomplete information in the current log.
684     //
685     // Logs recorded before a user login will be appended to user logs. This
686     // should not happen frequently.
687     //
688     // TODO(crbug/1264627): Look for a way to "pause" pre-login logs and flush
689     // when INIT_TASK is done.
690     log_store()->SetAlternateOngoingLogStore(std::move(user_log_store));
691     RecordUserLogStoreState(kSetPreSendLogsState);
692   }
693 }
694 
UnsetUserLogStore()695 void MetricsService::UnsetUserLogStore() {
696   if (!log_store()->has_alternate_ongoing_log_store())
697     return;
698 
699   if (state_ >= SENDING_LOGS) {
700     PushPendingLogsToPersistentStorage(
701         MetricsLogsEventManager::CreateReason::kAlternateOngoingLogStoreUnset);
702     log_store()->UnsetAlternateOngoingLogStore();
703     OpenNewLog();
704     RecordUserLogStoreState(kUnsetPostSendLogsState);
705     return;
706   }
707 
708   // Fast startup and logout case. We flush all histograms and discard the
709   // current log. This is to prevent histograms captured during the user
710   // session from leaking into local state logs.
711   // TODO(crbug/1381581): Consider not flushing histograms here.
712 
713   // Discard histograms.
714   DiscardingFlattener flattener;
715   base::HistogramSnapshotManager histogram_snapshot_manager(&flattener);
716   delegating_provider_.RecordHistogramSnapshots(&histogram_snapshot_manager);
717   base::StatisticsRecorder::PrepareDeltas(
718       /*include_persistent=*/true, /*flags_to_set=*/base::Histogram::kNoFlags,
719       /*required_flags=*/base::Histogram::kUmaTargetedHistogramFlag,
720       &histogram_snapshot_manager);
721 
722   // Discard the current log and don't store it.
723   CHECK(current_log_);
724   current_log_.reset();
725 
726   log_store()->UnsetAlternateOngoingLogStore();
727   RecordUserLogStoreState(kUnsetPreSendLogsState);
728 }
729 
HasUserLogStore()730 bool MetricsService::HasUserLogStore() {
731   return log_store()->has_alternate_ongoing_log_store();
732 }
733 
InitPerUserMetrics()734 void MetricsService::InitPerUserMetrics() {
735   client_->InitPerUserMetrics();
736 }
737 
GetCurrentUserMetricsConsent() const738 absl::optional<bool> MetricsService::GetCurrentUserMetricsConsent() const {
739   return client_->GetCurrentUserMetricsConsent();
740 }
741 
GetCurrentUserId() const742 absl::optional<std::string> MetricsService::GetCurrentUserId() const {
743   return client_->GetCurrentUserId();
744 }
745 
UpdateCurrentUserMetricsConsent(bool user_metrics_consent)746 void MetricsService::UpdateCurrentUserMetricsConsent(
747     bool user_metrics_consent) {
748   client_->UpdateCurrentUserMetricsConsent(user_metrics_consent);
749 }
750 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
751 
752 #if BUILDFLAG(IS_CHROMEOS)
ResetClientId()753 void MetricsService::ResetClientId() {
754   // Pref must be cleared in order for ForceClientIdCreation to generate a new
755   // client ID.
756   local_state_->ClearPref(prefs::kMetricsClientID);
757   local_state_->ClearPref(prefs::kMetricsLogRecordId);
758   state_manager_->ForceClientIdCreation();
759   client_->SetMetricsClientId(state_manager_->client_id());
760 }
761 #endif  // BUILDFLAG(IS_CHROMEOS)
762 
763 variations::SyntheticTrialRegistry*
GetSyntheticTrialRegistry()764 MetricsService::GetSyntheticTrialRegistry() {
765   return client_->GetSyntheticTrialRegistry();
766 }
767 
GetInitializationDelay()768 base::TimeDelta MetricsService::GetInitializationDelay() {
769   return base::Seconds(
770       client_->ShouldStartUpFastForTesting() ? 0 : kInitializationDelaySeconds);
771 }
772 
GetUpdateLastAliveTimestampDelay()773 base::TimeDelta MetricsService::GetUpdateLastAliveTimestampDelay() {
774   return base::Seconds(kUpdateAliveTimestampSeconds);
775 }
776 
StageCurrentLogForTest()777 bool MetricsService::StageCurrentLogForTest() {
778   CloseCurrentLog(/*async=*/false,
779                   MetricsLogsEventManager::CreateReason::kUnknown);
780 
781   MetricsLogStore* const log_store = reporting_service_.metrics_log_store();
782   log_store->StageNextLog();
783   if (!log_store->has_staged_log())
784     return false;
785 
786   OpenNewLog();
787   return true;
788 }
789 
790 //------------------------------------------------------------------------------
791 // private methods
792 //------------------------------------------------------------------------------
793 
794 //------------------------------------------------------------------------------
795 // Initialization methods
796 
InitializeMetricsState()797 void MetricsService::InitializeMetricsState() {
798   SCOPED_UMA_HISTOGRAM_TIMER_MICROS("UMA.MetricsService.Initialize.Time");
799 
800   const int64_t buildtime = MetricsLog::GetBuildTime();
801   const std::string version = client_->GetVersionString();
802 
803   bool version_changed = false;
804   EnvironmentRecorder recorder(local_state_);
805   int64_t previous_buildtime = recorder.GetLastBuildtime();
806   std::string previous_version = recorder.GetLastVersion();
807   if (previous_buildtime != buildtime || previous_version != version) {
808     recorder.SetBuildtimeAndVersion(buildtime, version);
809     version_changed = true;
810   }
811 
812   session_id_ = local_state_->GetInteger(prefs::kMetricsSessionID);
813 
814   StabilityMetricsProvider provider(local_state_);
815   const bool was_last_shutdown_clean = WasLastShutdownClean();
816   if (!was_last_shutdown_clean) {
817     provider.LogCrash(
818         state_manager_->clean_exit_beacon()->browser_last_live_timestamp());
819 #if BUILDFLAG(IS_ANDROID)
820     if (!state_manager_->is_foreground_session()) {
821       // Android can have background sessions in which the app may not come to
822       // the foreground, so signal that Chrome should stop watching for crashes
823       // here. This ensures that the termination of such sessions is not
824       // considered a crash. If and when the app enters the foreground, Chrome
825       // starts watching for crashes via MetricsService::OnAppEnterForeground().
826       //
827       // TODO(crbug/1232027): Such sessions do not yet exist on iOS. When they
828       // do, it may not be possible to know at this point whether a session is a
829       // background session.
830       //
831       // TODO(crbug/1245347): On WebLayer, it is not possible to know whether
832       // it's a background session at this point.
833       //
834       // TODO(crbug/1245676): Ditto for WebView.
835       state_manager_->clean_exit_beacon()->WriteBeaconValue(true);
836     }
837 #endif  // BUILDFLAG(IS_ANDROID)
838   }
839 
840   // HasPreviousSessionData is called first to ensure it is never bypassed.
841   const bool is_initial_stability_log_required =
842       delegating_provider_.HasPreviousSessionData() || !was_last_shutdown_clean;
843   bool has_initial_stability_log = false;
844   if (is_initial_stability_log_required) {
845     // If the previous session didn't exit cleanly, or if any provider
846     // explicitly requests it, prepare an initial stability log -
847     // provided UMA is enabled.
848     if (state_manager_->IsMetricsReportingEnabled()) {
849       has_initial_stability_log = PrepareInitialStabilityLog(previous_version);
850     }
851   }
852 
853   // If the version changed, but no initial stability log was generated, clear
854   // the stability stats from the previous version (so that they don't get
855   // attributed to the current version). This could otherwise happen due to a
856   // number of different edge cases, such as if the last version crashed before
857   // it could save off a system profile or if UMA reporting is disabled (which
858   // normally results in stats being accumulated).
859   if (version_changed && !has_initial_stability_log)
860     ClearSavedStabilityMetrics();
861 
862   // If the version changed, the system profile is obsolete and needs to be
863   // cleared. This is to avoid the stability data misattribution that could
864   // occur if the current version crashed before saving its own system profile.
865   // Note however this clearing occurs only after preparing the initial
866   // stability log, an operation that requires the previous version's system
867   // profile. At this point, stability metrics pertaining to the previous
868   // version have been cleared.
869   if (version_changed)
870     recorder.ClearEnvironmentFromPrefs();
871 
872   // Update session ID.
873   ++session_id_;
874   local_state_->SetInteger(prefs::kMetricsSessionID, session_id_);
875 
876   // Notify stability metrics providers about the launch.
877   provider.LogLaunch();
878 
879   // Call GetUptimes() for the first time, thus allowing all later calls
880   // to record incremental uptimes accurately.
881   base::TimeDelta ignored_uptime_parameter;
882   base::TimeDelta startup_uptime;
883   GetUptimes(local_state_, &startup_uptime, &ignored_uptime_parameter);
884   DCHECK_EQ(0, startup_uptime.InMicroseconds());
885 }
886 
OnUserAction(const std::string & action,base::TimeTicks action_time)887 void MetricsService::OnUserAction(const std::string& action,
888                                   base::TimeTicks action_time) {
889   current_log_->RecordUserAction(action, action_time);
890   HandleIdleSinceLastTransmission(false);
891 }
892 
FinishedInitTask()893 void MetricsService::FinishedInitTask() {
894   DCHECK_EQ(INIT_TASK_SCHEDULED, state_);
895   state_ = INIT_TASK_DONE;
896   rotation_scheduler_->InitTaskComplete();
897 }
898 
GetUptimes(PrefService * pref,base::TimeDelta * incremental_uptime,base::TimeDelta * uptime)899 void MetricsService::GetUptimes(PrefService* pref,
900                                 base::TimeDelta* incremental_uptime,
901                                 base::TimeDelta* uptime) {
902   base::TimeTicks now = base::TimeTicks::Now();
903   // If this is the first call, init |first_updated_time_| and
904   // |last_updated_time_|.
905   if (last_updated_time_.is_null()) {
906     first_updated_time_ = now;
907     last_updated_time_ = now;
908   }
909   *incremental_uptime = now - last_updated_time_;
910   *uptime = now - first_updated_time_;
911   last_updated_time_ = now;
912 }
913 
914 //------------------------------------------------------------------------------
915 // Recording control methods
916 
OpenNewLog(bool call_providers)917 void MetricsService::OpenNewLog(bool call_providers) {
918   CHECK(!current_log_);
919 
920   current_log_ = CreateLog(MetricsLog::ONGOING_LOG);
921   if (call_providers) {
922     delegating_provider_.OnDidCreateMetricsLog();
923   }
924 
925   DCHECK_NE(CONSTRUCTED, state_);
926   if (state_ == INITIALIZED) {
927     // We only need to schedule that run once.
928     state_ = INIT_TASK_SCHEDULED;
929 
930     base::TimeDelta initialization_delay = GetInitializationDelay();
931     base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
932         FROM_HERE,
933         base::BindOnce(&MetricsService::StartInitTask,
934                        self_ptr_factory_.GetWeakPtr()),
935         initialization_delay);
936 
937     base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
938         FROM_HERE,
939         base::BindOnce(&MetricsService::PrepareProviderMetricsTask,
940                        self_ptr_factory_.GetWeakPtr()),
941         2 * initialization_delay);
942   }
943 }
944 
945 MetricsService::FinalizedLog::FinalizedLog() = default;
946 MetricsService::FinalizedLog::~FinalizedLog() = default;
947 MetricsService::FinalizedLog::FinalizedLog(FinalizedLog&& other) = default;
948 MetricsService::FinalizedLog& MetricsService::FinalizedLog::operator=(
949     FinalizedLog&& other) = default;
950 
MetricsLogHistogramWriter(MetricsLog * log)951 MetricsService::MetricsLogHistogramWriter::MetricsLogHistogramWriter(
952     MetricsLog* log)
953     : MetricsLogHistogramWriter(log,
954                                 base::Histogram::kUmaTargetedHistogramFlag) {}
955 
MetricsLogHistogramWriter(MetricsLog * log,base::HistogramBase::Flags required_flags)956 MetricsService::MetricsLogHistogramWriter::MetricsLogHistogramWriter(
957     MetricsLog* log,
958     base::HistogramBase::Flags required_flags)
959     : required_flags_(required_flags),
960       flattener_(std::make_unique<IndependentFlattener>(log)),
961       histogram_snapshot_manager_(
962           std::make_unique<base::HistogramSnapshotManager>(flattener_.get())),
963       snapshot_transaction_id_(0) {}
964 
965 MetricsService::MetricsLogHistogramWriter::~MetricsLogHistogramWriter() =
966     default;
967 
968 void MetricsService::MetricsLogHistogramWriter::
SnapshotStatisticsRecorderDeltas()969     SnapshotStatisticsRecorderDeltas() {
970   SCOPED_UMA_HISTOGRAM_TIMER("UMA.MetricsService.SnapshotDeltasTime");
971   snapshot_transaction_id_ = base::StatisticsRecorder::PrepareDeltas(
972       /*include_persistent=*/true,
973       /*flags_to_set=*/base::Histogram::kNoFlags, required_flags_,
974       histogram_snapshot_manager_.get());
975 }
976 
977 void MetricsService::MetricsLogHistogramWriter::
SnapshotStatisticsRecorderUnloggedSamples()978     SnapshotStatisticsRecorderUnloggedSamples() {
979   snapshot_transaction_id_ = base::StatisticsRecorder::SnapshotUnloggedSamples(
980       required_flags_, histogram_snapshot_manager_.get());
981 }
982 
IndependentMetricsLoader(std::unique_ptr<MetricsLog> log,std::string app_version,std::string signing_key)983 MetricsService::IndependentMetricsLoader::IndependentMetricsLoader(
984     std::unique_ptr<MetricsLog> log,
985     std::string app_version,
986     std::string signing_key)
987     : log_(std::move(log)),
988       flattener_(new IndependentFlattener(log_.get())),
989       snapshot_manager_(new base::HistogramSnapshotManager(flattener_.get())),
990       app_version_(std::move(app_version)),
991       signing_key_(std::move(signing_key)) {
992   CHECK(log_);
993   CHECK_EQ(log_->log_type(), MetricsLog::INDEPENDENT_LOG);
994 }
995 
996 MetricsService::IndependentMetricsLoader::~IndependentMetricsLoader() = default;
997 
Run(base::OnceCallback<void (bool)> done_callback,MetricsProvider * metrics_provider)998 void MetricsService::IndependentMetricsLoader::Run(
999     base::OnceCallback<void(bool)> done_callback,
1000     MetricsProvider* metrics_provider) {
1001   CHECK(!run_called_);
1002   run_called_ = true;
1003 
1004   metrics_provider->ProvideIndependentMetrics(
1005       // Unretained is safe because this callback is either called before
1006       // |done_callback|, or in |done_callback|. Either case is fine because
1007       // |done_callback| owns |this|.
1008       base::BindOnce(&MetricsService::IndependentMetricsLoader::FinalizeLog,
1009                      base::Unretained(this)),
1010       std::move(done_callback), log_->uma_proto(), snapshot_manager_.get());
1011 }
1012 
FinalizeLog()1013 void MetricsService::IndependentMetricsLoader::FinalizeLog() {
1014   CHECK(run_called_);
1015   CHECK(!finalize_log_called_);
1016   finalize_log_called_ = true;
1017 
1018   // Release |snapshot_manager_| and then |flattener_| to prevent dangling
1019   // pointers, since |log_| will be released in MetricsService::FinalizeLog().
1020   snapshot_manager_.reset();
1021   flattener_.reset();
1022 
1023   // Note that the close_time param must not be set for independent logs.
1024   finalized_log_ = MetricsService::FinalizeLog(
1025       std::move(log_), /*truncate_events=*/false, /*close_time=*/absl::nullopt,
1026       app_version_, signing_key_);
1027 }
1028 
HasFinalizedLog()1029 bool MetricsService::IndependentMetricsLoader::HasFinalizedLog() {
1030   return finalize_log_called_ && !release_finalized_log_called_;
1031 }
1032 
1033 MetricsService::FinalizedLog
ReleaseFinalizedLog()1034 MetricsService::IndependentMetricsLoader::ReleaseFinalizedLog() {
1035   CHECK(HasFinalizedLog());
1036 
1037   release_finalized_log_called_ = true;
1038   return std::move(finalized_log_);
1039 }
1040 
StartInitTask()1041 void MetricsService::StartInitTask() {
1042   delegating_provider_.AsyncInit(base::BindOnce(
1043       &MetricsService::FinishedInitTask, self_ptr_factory_.GetWeakPtr()));
1044 }
1045 
CloseCurrentLog(bool async,MetricsLogsEventManager::CreateReason reason,base::OnceClosure log_stored_callback)1046 void MetricsService::CloseCurrentLog(
1047     bool async,
1048     MetricsLogsEventManager::CreateReason reason,
1049     base::OnceClosure log_stored_callback) {
1050   if (!current_log_) {
1051     return;
1052   }
1053 
1054   // If a persistent allocator is in use, update its internal histograms (such
1055   // as how much memory is being used) before reporting.
1056   base::PersistentHistogramAllocator* allocator =
1057       base::GlobalHistogramAllocator::Get();
1058   if (allocator)
1059     allocator->UpdateTrackingHistograms();
1060 
1061   // Put incremental data (histogram deltas, and realtime stats deltas) at the
1062   // end of all log transmissions (initial log handles this separately).
1063   // RecordIncrementalStabilityElements only exists on the derived
1064   // MetricsLog class.
1065   std::unique_ptr<MetricsLog> current_log(std::move(current_log_));
1066   RecordCurrentEnvironment(current_log.get(), /*complete=*/true);
1067   base::TimeDelta incremental_uptime;
1068   base::TimeDelta uptime;
1069   GetUptimes(local_state_, &incremental_uptime, &uptime);
1070   current_log->RecordCurrentSessionData(incremental_uptime, uptime,
1071                                         &delegating_provider_, local_state_);
1072 
1073   auto log_histogram_writer =
1074       std::make_unique<MetricsLogHistogramWriter>(current_log.get());
1075 
1076   // Let metrics providers provide histogram snapshots independently if they
1077   // have any. This is done synchronously.
1078   delegating_provider_.RecordHistogramSnapshots(
1079       log_histogram_writer->histogram_snapshot_manager());
1080 
1081   MetricsLog::LogType log_type = current_log->log_type();
1082   CHECK_EQ(log_type, MetricsLog::ONGOING_LOG);
1083   ChromeUserMetricsExtension::RealLocalTime close_time =
1084       current_log->GetCurrentClockTime(/*record_time_zone=*/true);
1085   std::string signing_key = log_store()->GetSigningKeyForLogType(log_type);
1086   std::string current_app_version = client_->GetVersionString();
1087 
1088 #if !BUILDFLAG(IS_ANDROID)
1089   if (base::FeatureList::IsEnabled(
1090           features::kMetricsServiceDeltaSnapshotInBg)) {
1091     // If this is an async periodic log, and the browser is about to be shut
1092     // down (determined by KeepAliveRegistry::IsShuttingDown(), indicating that
1093     // there is nothing else to keep the browser alive), then do the work
1094     // synchronously instead. Otherwise, creating a ScopedKeepAlive below while
1095     // the KeepAliveRegistry has already started shutting down will trigger a
1096     // CHECK. Alternatively, the ScopedKeepAlive below could be omitted when the
1097     // KeepAliveRegistry is shutting down, but since the browser is shutting
1098     // down soon, then it is likely that the asynchronous task to close the
1099     // current the log will be cut short, causing data loss.
1100     if (async && KeepAliveRegistry::GetInstance()->IsShuttingDown()) {
1101       async = false;
1102     }
1103   }
1104 #endif
1105 
1106   if (async) {
1107     if (base::FeatureList::IsEnabled(
1108             features::kMetricsServiceDeltaSnapshotInBg)) {
1109       // In this mode, we perform the full "delta snapshot" (snapshotting
1110       // unlogged samples and marking them as logged) in the background, in
1111       // contrast to snapshotting unlogged samples in the background and marking
1112       // them as logged when back on the main thread, as is done in the else
1113       // branch.
1114 
1115       auto background_task = base::BindOnce(
1116           &MetricsService::SnapshotDeltasAndFinalizeLog,
1117           std::move(log_histogram_writer), std::move(current_log),
1118           /*truncate_events=*/true, std::move(close_time),
1119           std::move(current_app_version), std::move(signing_key));
1120       auto reply_task = base::BindOnce(&MetricsService::StoreFinalizedLog,
1121                                        self_ptr_factory_.GetWeakPtr(), log_type,
1122                                        reason, std::move(log_stored_callback));
1123 
1124 #if !BUILDFLAG(IS_ANDROID)
1125       // Prevent the browser from shutting down while creating the log in the
1126       // background. This is done by creating a ScopedKeepAlive that is only
1127       // destroyed after the log has been stored. Not used on Android because it
1128       // has no shutdown code path.
1129       reply_task = std::move(reply_task)
1130                        .Then(base::BindOnce(
1131                            [](std::unique_ptr<ScopedKeepAlive>) {
1132                              // This function does nothing but keep the
1133                              // ScopedKeepAlive param alive until we have
1134                              // finished storing the log.
1135                            },
1136                            std::make_unique<ScopedKeepAlive>(
1137                                KeepAliveOrigin::UMA_LOG,
1138                                KeepAliveRestartOption::DISABLED)));
1139 #endif  // !BUILDFLAG(IS_ANDROID)
1140 
1141       base::ThreadPool::PostTaskAndReplyWithResult(
1142           FROM_HERE,
1143           {base::TaskPriority::USER_BLOCKING,
1144            base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
1145           std::move(background_task), std::move(reply_task));
1146     } else {
1147       // To finalize the log asynchronously, we snapshot the unlogged samples of
1148       // histograms and fill them into the log, without actually marking the
1149       // samples as logged. We only mark them as logged after running the main
1150       // thread reply task to store the log. This way, we will not lose the
1151       // samples in case Chrome closes while the background task is running.
1152       // Note that while this async log is being finalized, it is possible that
1153       // another log is finalized and stored synchronously, which could
1154       // potentially cause the same samples to be in two different logs, and
1155       // hence sent twice. To prevent this, if a synchronous log is stored while
1156       // the async one is being finalized, we discard the async log as it would
1157       // be a subset of the synchronous one (in terms of histograms). For more
1158       // details, see MaybeCleanUpAndStoreFinalizedLog().
1159       //
1160       // TODO(crbug/1052796): Find a way to save the other data such as user
1161       // actions and omnibox events when we discard an async log.
1162       MetricsLogHistogramWriter* log_histogram_writer_ptr =
1163           log_histogram_writer.get();
1164       base::ThreadPool::PostTaskAndReplyWithResult(
1165           FROM_HERE,
1166           // CONTINUE_ON_SHUTDOWN because the work done is only useful once the
1167           // reply task is run (and there are no side effects). So, no need to
1168           // block shutdown since the reply task won't be run anyway.
1169           // NOTE: If attempting to change the USER_BLOCKING priority, do a
1170           // study on the impact first since it might affect the number of logs
1171           // being uploaded (which might have secondary effects, e.g. on metrics
1172           // that rely on number of logs uploaded).
1173           {base::TaskPriority::USER_BLOCKING,
1174            base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
1175           base::BindOnce(&MetricsService::SnapshotUnloggedSamplesAndFinalizeLog,
1176                          log_histogram_writer_ptr, std::move(current_log),
1177                          /*truncate_events=*/true, std::move(close_time),
1178                          std::move(current_app_version),
1179                          std::move(signing_key)),
1180           base::BindOnce(&MetricsService::MaybeCleanUpAndStoreFinalizedLog,
1181                          self_ptr_factory_.GetWeakPtr(),
1182                          std::move(log_histogram_writer), log_type, reason,
1183                          std::move(log_stored_callback)));
1184       async_ongoing_log_posted_time_ = base::TimeTicks::Now();
1185     }
1186   } else {
1187     FinalizedLog finalized_log = SnapshotDeltasAndFinalizeLog(
1188         std::move(log_histogram_writer), std::move(current_log),
1189         /*truncate_events=*/true, std::move(close_time),
1190         std::move(current_app_version), std::move(signing_key));
1191     StoreFinalizedLog(log_type, reason, std::move(log_stored_callback),
1192                       std::move(finalized_log));
1193   }
1194 }
1195 
StoreFinalizedLog(MetricsLog::LogType log_type,MetricsLogsEventManager::CreateReason reason,base::OnceClosure done_callback,FinalizedLog finalized_log)1196 void MetricsService::StoreFinalizedLog(
1197     MetricsLog::LogType log_type,
1198     MetricsLogsEventManager::CreateReason reason,
1199     base::OnceClosure done_callback,
1200     FinalizedLog finalized_log) {
1201   log_store()->StoreLogInfo(std::move(finalized_log.log_info),
1202                             finalized_log.uncompressed_log_size, log_type,
1203                             reason);
1204   std::move(done_callback).Run();
1205 }
1206 
MaybeCleanUpAndStoreFinalizedLog(std::unique_ptr<MetricsLogHistogramWriter> log_histogram_writer,MetricsLog::LogType log_type,MetricsLogsEventManager::CreateReason reason,base::OnceClosure done_callback,FinalizedLog finalized_log)1207 void MetricsService::MaybeCleanUpAndStoreFinalizedLog(
1208     std::unique_ptr<MetricsLogHistogramWriter> log_histogram_writer,
1209     MetricsLog::LogType log_type,
1210     MetricsLogsEventManager::CreateReason reason,
1211     base::OnceClosure done_callback,
1212     FinalizedLog finalized_log) {
1213   UMA_HISTOGRAM_TIMES("UMA.MetricsService.PeriodicOngoingLog.ReplyTime",
1214                       base::TimeTicks::Now() - async_ongoing_log_posted_time_);
1215 
1216   // Store the finalized log only if the StatisticRecorder's last transaction ID
1217   // is the same as the one from |log_histogram_writer|. If they are not the
1218   // same, then it indicates that another log was created while creating
1219   // |finalized_log| (that log would be a superset of |finalized_log| in terms
1220   // of histograms, so we discard |finalized_log| by not storing it).
1221   //
1222   // TODO(crbug/1052796): Find a way to save the other data such as user actions
1223   // and omnibox events when we discard |finalized_log|.
1224   //
1225   // Note that the call to StatisticsRecorder::GetLastSnapshotTransactionId()
1226   // here should not have to wait for a lock since there should not be any async
1227   // logs being created (|rotation_scheduler_| is only re-scheduled at the end
1228   // of this method).
1229   bool should_store_log =
1230       (base::StatisticsRecorder::GetLastSnapshotTransactionId() ==
1231        log_histogram_writer->snapshot_transaction_id());
1232   base::UmaHistogramBoolean("UMA.MetricsService.ShouldStoreAsyncLog",
1233                             should_store_log);
1234 
1235   if (!should_store_log) {
1236     // We still need to run |done_callback| even if we do not store the log.
1237     std::move(done_callback).Run();
1238     return;
1239   }
1240 
1241   SCOPED_UMA_HISTOGRAM_TIMER(
1242       "UMA.MetricsService.MaybeCleanUpAndStoreFinalizedLog.Time");
1243 
1244   log_histogram_writer->histogram_snapshot_manager()
1245       ->MarkUnloggedSamplesAsLogged();
1246   StoreFinalizedLog(log_type, reason, std::move(done_callback),
1247                     std::move(finalized_log));
1248 }
1249 
PushPendingLogsToPersistentStorage(MetricsLogsEventManager::CreateReason reason)1250 void MetricsService::PushPendingLogsToPersistentStorage(
1251     MetricsLogsEventManager::CreateReason reason) {
1252   if (IsTooEarlyToCloseLog()) {
1253     return;
1254   }
1255 
1256   base::UmaHistogramBoolean("UMA.MetricsService.PendingOngoingLog",
1257                             pending_ongoing_log_);
1258 
1259   // Close and store a log synchronously because this is usually called in
1260   // critical code paths (e.g., shutdown) where we may not have time to run
1261   // background tasks.
1262   CloseCurrentLog(/*async=*/false, reason);
1263   log_store()->TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
1264 }
1265 
1266 //------------------------------------------------------------------------------
1267 // Transmission of logs methods
1268 
StartSchedulerIfNecessary()1269 void MetricsService::StartSchedulerIfNecessary() {
1270   // Never schedule cutting or uploading of logs in test mode.
1271   if (test_mode_active_)
1272     return;
1273 
1274   // Even if reporting is disabled, the scheduler is needed to trigger the
1275   // creation of the first ongoing log, which must be done in order for any logs
1276   // to be persisted on shutdown or backgrounding.
1277   if (recording_active() && (reporting_active() || state_ < SENDING_LOGS)) {
1278     rotation_scheduler_->Start();
1279     reporting_service_.Start();
1280   }
1281 }
1282 
StartScheduledUpload()1283 void MetricsService::StartScheduledUpload() {
1284   DVLOG(1) << "StartScheduledUpload";
1285   DCHECK(state_ >= INIT_TASK_DONE);
1286 
1287   // If we're getting no notifications, then the log won't have much in it, and
1288   // it's possible the computer is about to go to sleep, so don't upload and
1289   // stop the scheduler.
1290   // If recording has been turned off, the scheduler doesn't need to run.
1291   // If reporting is off, proceed if the first ongoing log hasn't been created,
1292   // since that has to happen in order for logs to be cut and stored when
1293   // persisting.
1294   // TODO(stuartmorgan): Call Stop() on the scheduler when reporting and/or
1295   // recording are turned off instead of letting it fire and then aborting.
1296   if (idle_since_last_transmission_ || !recording_active() ||
1297       (!reporting_active() && state_ >= SENDING_LOGS)) {
1298     rotation_scheduler_->Stop();
1299     rotation_scheduler_->RotationFinished();
1300     return;
1301   }
1302 
1303   // The first ongoing log should be collected prior to sending any unsent logs.
1304   if (state_ == INIT_TASK_DONE) {
1305     client_->CollectFinalMetricsForLog(
1306         base::BindOnce(&MetricsService::OnFinalLogInfoCollectionDone,
1307                        self_ptr_factory_.GetWeakPtr()));
1308     return;
1309   }
1310 
1311   // If there are unsent logs, send the next one. If not, start the asynchronous
1312   // process of finalizing the current log for upload.
1313   if (has_unsent_logs()) {
1314     reporting_service_.Start();
1315     rotation_scheduler_->RotationFinished();
1316   } else {
1317     // There are no logs left to send, so start creating a new one.
1318     client_->CollectFinalMetricsForLog(
1319         base::BindOnce(&MetricsService::OnFinalLogInfoCollectionDone,
1320                        self_ptr_factory_.GetWeakPtr()));
1321   }
1322 }
1323 
OnFinalLogInfoCollectionDone()1324 void MetricsService::OnFinalLogInfoCollectionDone() {
1325   DVLOG(1) << "OnFinalLogInfoCollectionDone";
1326   DCHECK(state_ >= INIT_TASK_DONE);
1327   state_ = SENDING_LOGS;
1328 
1329   // Abort if metrics were turned off during the final info gathering.
1330   if (!recording_active()) {
1331     rotation_scheduler_->Stop();
1332     rotation_scheduler_->RotationFinished();
1333     return;
1334   }
1335 
1336   SCOPED_UMA_HISTOGRAM_TIMER("UMA.MetricsService.PeriodicOngoingLog.CloseTime");
1337 
1338   // There shouldn't be two periodic ongoing logs being finalized in the
1339   // background simultaneously. This is currently enforced because:
1340   // 1. Only periodic ongoing logs are finalized asynchronously (i.e., logs
1341   //    created by the MetricsRotationScheduler).
1342   // 2. We only re-schedule the MetricsRotationScheduler after storing a
1343   //    periodic ongoing log.
1344   //
1345   // TODO(crbug/1052796): Consider making it possible to have multiple
1346   // simultaneous async logs by having some queueing system (e.g., if we want
1347   // the log created when foregrounding Chrome to be async).
1348   DCHECK(!pending_ongoing_log_);
1349   pending_ongoing_log_ = true;
1350 
1351   base::OnceClosure log_stored_callback =
1352       base::BindOnce(&MetricsService::OnAsyncPeriodicOngoingLogStored,
1353                      self_ptr_factory_.GetWeakPtr());
1354   CloseCurrentLog(/*async=*/true,
1355                   MetricsLogsEventManager::CreateReason::kPeriodic,
1356                   std::move(log_stored_callback));
1357   OpenNewLog(/*call_providers=*/false);
1358 }
1359 
OnAsyncPeriodicOngoingLogStored()1360 void MetricsService::OnAsyncPeriodicOngoingLogStored() {
1361   pending_ongoing_log_ = false;
1362 
1363   // Call OnDidCreateMetricsLog() after storing a log instead of directly after
1364   // opening a log. Otherwise, the async log that was created would potentially
1365   // have mistakenly snapshotted the histograms intended for the newly opened
1366   // log.
1367   delegating_provider_.OnDidCreateMetricsLog();
1368 
1369   // Trim and store unsent logs, including the log that was just closed, so that
1370   // they're not lost in case of a crash before upload time. However, the
1371   // in-memory log store is unchanged. I.e., logs that are trimmed will still be
1372   // available in memory. This is to give the log that was just created a chance
1373   // to be sent in case it is trimmed. After uploading (whether successful or
1374   // not), the log store is trimmed and stored again, and at that time, the
1375   // in-memory log store will be updated.
1376   log_store()->TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/false);
1377 
1378   // Do not re-schedule if metrics were turned off while finalizing the log.
1379   if (!recording_active()) {
1380     rotation_scheduler_->Stop();
1381     rotation_scheduler_->RotationFinished();
1382   } else {
1383     // Only re-schedule |rotation_scheduler_| *after* the log was stored to
1384     // ensure that only one log is created asynchronously at a time.
1385     reporting_service_.Start();
1386     rotation_scheduler_->RotationFinished();
1387     HandleIdleSinceLastTransmission(true);
1388   }
1389 }
1390 
PrepareInitialStabilityLog(const std::string & prefs_previous_version)1391 bool MetricsService::PrepareInitialStabilityLog(
1392     const std::string& prefs_previous_version) {
1393   DCHECK_EQ(CONSTRUCTED, state_);
1394 
1395   MetricsLog::LogType log_type = MetricsLog::INITIAL_STABILITY_LOG;
1396   std::unique_ptr<MetricsLog> initial_stability_log(CreateLog(log_type));
1397 
1398   // Do not call OnDidCreateMetricsLog here because the stability log describes
1399   // stats from the _previous_ session.
1400 
1401   if (!initial_stability_log->LoadSavedEnvironmentFromPrefs(local_state_))
1402     return false;
1403 
1404   initial_stability_log->RecordPreviousSessionData(&delegating_provider_,
1405                                                    local_state_);
1406 
1407   auto log_histogram_writer = std::make_unique<MetricsLogHistogramWriter>(
1408       initial_stability_log.get(), base::Histogram::kUmaStabilityHistogramFlag);
1409 
1410   // Add a beacon to this record to indicate that it's part of the initial
1411   // stability log.
1412   UMA_STABILITY_HISTOGRAM_BOOLEAN("UMA.InitialStabilityRecordBeacon", true);
1413 
1414   // Let metrics providers provide histogram snapshots independently if they
1415   // have any. This is done synchronously.
1416   delegating_provider_.RecordInitialHistogramSnapshots(
1417       log_histogram_writer->histogram_snapshot_manager());
1418 
1419   std::string signing_key = log_store()->GetSigningKeyForLogType(log_type);
1420 
1421   // Synchronously create the initial stability log in order to ensure that the
1422   // stability histograms are filled into this specific log. Note that the
1423   // close_time param must not be set for initial stability logs.
1424   FinalizedLog finalized_log = SnapshotDeltasAndFinalizeLog(
1425       std::move(log_histogram_writer), std::move(initial_stability_log),
1426       /*truncate_events=*/false, /*close_time=*/absl::nullopt,
1427       client_->GetVersionString(), std::move(signing_key));
1428   StoreFinalizedLog(log_type, MetricsLogsEventManager::CreateReason::kStability,
1429                     base::DoNothing(), std::move(finalized_log));
1430 
1431   // Store unsent logs, including the stability log that was just saved, so
1432   // that they're not lost in case of a crash before upload time.
1433   log_store()->TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
1434 
1435   return true;
1436 }
1437 
RegisterMetricsProvider(std::unique_ptr<MetricsProvider> provider)1438 void MetricsService::RegisterMetricsProvider(
1439     std::unique_ptr<MetricsProvider> provider) {
1440   DCHECK_EQ(CONSTRUCTED, state_);
1441   delegating_provider_.RegisterMetricsProvider(std::move(provider));
1442 }
1443 
CheckForClonedInstall()1444 void MetricsService::CheckForClonedInstall() {
1445   state_manager_->CheckForClonedInstall();
1446 }
1447 
ShouldResetClientIdsOnClonedInstall()1448 bool MetricsService::ShouldResetClientIdsOnClonedInstall() {
1449   return state_manager_->ShouldResetClientIdsOnClonedInstall();
1450 }
1451 
CreateLog(MetricsLog::LogType log_type)1452 std::unique_ptr<MetricsLog> MetricsService::CreateLog(
1453     MetricsLog::LogType log_type) {
1454   auto new_metrics_log = std::make_unique<MetricsLog>(
1455       state_manager_->client_id(), session_id_, log_type, client_);
1456   new_metrics_log->AssignRecordId(local_state_);
1457 
1458 #if BUILDFLAG(IS_CHROMEOS_ASH)
1459   absl::optional<std::string> user_id = GetCurrentUserId();
1460   if (user_id.has_value())
1461     new_metrics_log->SetUserId(user_id.value());
1462 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
1463 
1464   return new_metrics_log;
1465 }
1466 
AddLogsObserver(MetricsLogsEventManager::Observer * observer)1467 void MetricsService::AddLogsObserver(
1468     MetricsLogsEventManager::Observer* observer) {
1469   logs_event_manager_.AddObserver(observer);
1470 }
1471 
RemoveLogsObserver(MetricsLogsEventManager::Observer * observer)1472 void MetricsService::RemoveLogsObserver(
1473     MetricsLogsEventManager::Observer* observer) {
1474   logs_event_manager_.RemoveObserver(observer);
1475 }
1476 
AddEnablementObserver(const base::RepeatingCallback<void (bool)> & observer)1477 base::CallbackListSubscription MetricsService::AddEnablementObserver(
1478     const base::RepeatingCallback<void(bool)>& observer) {
1479   return enablement_observers_.Add(observer);
1480 }
1481 
SetPersistentSystemProfile(const std::string & serialized_proto,bool complete)1482 void MetricsService::SetPersistentSystemProfile(
1483     const std::string& serialized_proto,
1484     bool complete) {
1485   GlobalPersistentSystemProfile::GetInstance()->SetSystemProfile(
1486       serialized_proto, complete);
1487 }
1488 
1489 // static
RecordCurrentEnvironmentHelper(MetricsLog * log,PrefService * local_state,DelegatingProvider * delegating_provider)1490 std::string MetricsService::RecordCurrentEnvironmentHelper(
1491     MetricsLog* log,
1492     PrefService* local_state,
1493     DelegatingProvider* delegating_provider) {
1494   const SystemProfileProto& system_profile =
1495       log->RecordEnvironment(delegating_provider);
1496   EnvironmentRecorder recorder(local_state);
1497   return recorder.SerializeAndRecordEnvironmentToPrefs(system_profile);
1498 }
1499 
RecordCurrentEnvironment(MetricsLog * log,bool complete)1500 void MetricsService::RecordCurrentEnvironment(MetricsLog* log, bool complete) {
1501   DCHECK(client_);
1502   std::string serialized_proto =
1503       RecordCurrentEnvironmentHelper(log, local_state_, &delegating_provider_);
1504 
1505   SetPersistentSystemProfile(serialized_proto, complete);
1506   client_->OnEnvironmentUpdate(&serialized_proto);
1507 
1508   // The call to SetPersistentSystemProfile() above will have written the
1509   // current system profile to persistent memory. Because it may span over
1510   // multiple pages, it is possible that the system profile may become corrupted
1511   // if only certain pages were flushed to disk. For example, say we overwrite
1512   // the persistent memory's system profile with a newer one, and that it spans
1513   // over two pages. Then, the OS flushes the second page, but not the first
1514   // page. If the device is shut down unexpectedly, e.g. due to a power outage,
1515   // then the first page will contain the beginning of the old system profile,
1516   // while the second page will contain the ending of the new system profile,
1517   // resulting in an unparsable system profile and rendering the whole file
1518   // useless. So, manually schedule a flush every time we overwrite the system
1519   // profile with a new one to ensure we don't ever get a corrupted one.
1520   if (base::FeatureList::IsEnabled(
1521           features::kFlushPersistentSystemProfileOnWrite)) {
1522     base::ThreadPool::PostTask(
1523         FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
1524         base::BindOnce([]() {
1525           if (auto* allocator = base::GlobalHistogramAllocator::Get()) {
1526             // Ideally, we'd just call Flush() with the |sync| parameter set to
1527             // false on the main thread, but Windows does not support async
1528             // flushing, so do this synchronously on a background thread
1529             // instead.
1530             allocator->memory_allocator()->Flush(/*sync=*/true);
1531           }
1532         }));
1533   }
1534 }
1535 
PrepareProviderMetricsLogDone(std::unique_ptr<IndependentMetricsLoader> loader,bool success)1536 void MetricsService::PrepareProviderMetricsLogDone(
1537     std::unique_ptr<IndependentMetricsLoader> loader,
1538     bool success) {
1539   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1540   DCHECK(independent_loader_active_);
1541   DCHECK(loader);
1542 
1543   if (success) {
1544     // If not already done, finalize the log that was created independently by
1545     // the metrics provider.
1546     if (!loader->HasFinalizedLog()) {
1547       loader->FinalizeLog();
1548     }
1549 
1550     StoreFinalizedLog(MetricsLog::INDEPENDENT_LOG,
1551                       MetricsLogsEventManager::CreateReason::kIndependent,
1552                       /*done_callback=*/base::DoNothing(),
1553                       loader->ReleaseFinalizedLog());
1554   }
1555 
1556   independent_loader_active_ = false;
1557 }
1558 
PrepareProviderMetricsLog()1559 bool MetricsService::PrepareProviderMetricsLog() {
1560   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1561 
1562   // If something is still pending, stop now and indicate that there is
1563   // still work to do.
1564   if (independent_loader_active_)
1565     return true;
1566 
1567   // Check each provider in turn for data.
1568   for (auto& provider : delegating_provider_.GetProviders()) {
1569     if (provider->HasIndependentMetrics()) {
1570       // Create a new log. This will have some default values injected in it
1571       // but those will be overwritten when an embedded profile is extracted.
1572       std::unique_ptr<MetricsLog> log = CreateLog(MetricsLog::INDEPENDENT_LOG);
1573 
1574       // Note that something is happening. This must be set before the
1575       // operation is requested in case the loader decides to do everything
1576       // immediately rather than as a background task.
1577       independent_loader_active_ = true;
1578 
1579       // Give the new log to a loader for management and then run it on the
1580       // provider that has something to give. A copy of the pointer is needed
1581       // because the unique_ptr may get moved before the value can be used
1582       // to call Run().
1583       std::unique_ptr<IndependentMetricsLoader> loader =
1584           std::make_unique<IndependentMetricsLoader>(
1585               std::move(log), client_->GetVersionString(),
1586               log_store()->GetSigningKeyForLogType(
1587                   MetricsLog::INDEPENDENT_LOG));
1588       IndependentMetricsLoader* loader_ptr = loader.get();
1589       loader_ptr->Run(
1590           base::BindOnce(&MetricsService::PrepareProviderMetricsLogDone,
1591                          self_ptr_factory_.GetWeakPtr(), std::move(loader)),
1592           provider.get());
1593 
1594       // Something was found so there may still be more work to do.
1595       return true;
1596     }
1597   }
1598 
1599   // Nothing was found so indicate there is no more work to do.
1600   return false;
1601 }
1602 
PrepareProviderMetricsTask()1603 void MetricsService::PrepareProviderMetricsTask() {
1604   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1605   bool found = PrepareProviderMetricsLog();
1606   base::TimeDelta next_check = found ? base::Seconds(5) : base::Minutes(15);
1607   base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
1608       FROM_HERE,
1609       base::BindOnce(&MetricsService::PrepareProviderMetricsTask,
1610                      self_ptr_factory_.GetWeakPtr()),
1611       next_check);
1612 }
1613 
UpdateLastLiveTimestampTask()1614 void MetricsService::UpdateLastLiveTimestampTask() {
1615   state_manager_->clean_exit_beacon()->UpdateLastLiveTimestamp();
1616 
1617   // Schecule the next update.
1618   StartUpdatingLastLiveTimestamp();
1619 }
1620 
IsTooEarlyToCloseLog()1621 bool MetricsService::IsTooEarlyToCloseLog() {
1622   // When kMetricsServiceAllowEarlyLogClose is enabled, start closing logs as
1623   // soon as the first log is opened (|state_| is set to INIT_TASK_SCHEDULED
1624   // when the first log is opened, see OpenNewLog()). Otherwise, only start
1625   // closing logs when logs have started being sent.
1626   return base::FeatureList::IsEnabled(
1627              features::kMetricsServiceAllowEarlyLogClose)
1628              ? state_ < INIT_TASK_SCHEDULED
1629              : state_ < SENDING_LOGS;
1630 }
1631 
OnClonedInstallDetected()1632 void MetricsService::OnClonedInstallDetected() {
1633   // Purge all logs, as they may come from a previous install. Unfortunately,
1634   // since the cloned install detector works asynchronously, it is possible that
1635   // this is called after logs were already sent. However, practically speaking,
1636   // this should not happen, since logs are only sent late into the session.
1637   reporting_service_.metrics_log_store()->Purge();
1638 }
1639 
1640 // static
SnapshotDeltasAndFinalizeLog(std::unique_ptr<MetricsLogHistogramWriter> log_histogram_writer,std::unique_ptr<MetricsLog> log,bool truncate_events,absl::optional<ChromeUserMetricsExtension::RealLocalTime> close_time,std::string && current_app_version,std::string && signing_key)1641 MetricsService::FinalizedLog MetricsService::SnapshotDeltasAndFinalizeLog(
1642     std::unique_ptr<MetricsLogHistogramWriter> log_histogram_writer,
1643     std::unique_ptr<MetricsLog> log,
1644     bool truncate_events,
1645     absl::optional<ChromeUserMetricsExtension::RealLocalTime> close_time,
1646     std::string&& current_app_version,
1647     std::string&& signing_key) {
1648   log_histogram_writer->SnapshotStatisticsRecorderDeltas();
1649   return FinalizeLog(std::move(log), truncate_events, std::move(close_time),
1650                      current_app_version, signing_key);
1651 }
1652 
1653 // static
1654 MetricsService::FinalizedLog
SnapshotUnloggedSamplesAndFinalizeLog(MetricsLogHistogramWriter * log_histogram_writer,std::unique_ptr<MetricsLog> log,bool truncate_events,absl::optional<ChromeUserMetricsExtension::RealLocalTime> close_time,std::string && current_app_version,std::string && signing_key)1655 MetricsService::SnapshotUnloggedSamplesAndFinalizeLog(
1656     MetricsLogHistogramWriter* log_histogram_writer,
1657     std::unique_ptr<MetricsLog> log,
1658     bool truncate_events,
1659     absl::optional<ChromeUserMetricsExtension::RealLocalTime> close_time,
1660     std::string&& current_app_version,
1661     std::string&& signing_key) {
1662   log_histogram_writer->SnapshotStatisticsRecorderUnloggedSamples();
1663   return FinalizeLog(std::move(log), truncate_events, std::move(close_time),
1664                      current_app_version, signing_key);
1665 }
1666 
1667 // static
FinalizeLog(std::unique_ptr<MetricsLog> log,bool truncate_events,absl::optional<ChromeUserMetricsExtension::RealLocalTime> close_time,const std::string & current_app_version,const std::string & signing_key)1668 MetricsService::FinalizedLog MetricsService::FinalizeLog(
1669     std::unique_ptr<MetricsLog> log,
1670     bool truncate_events,
1671     absl::optional<ChromeUserMetricsExtension::RealLocalTime> close_time,
1672     const std::string& current_app_version,
1673     const std::string& signing_key) {
1674   DCHECK(log->uma_proto()->has_record_id());
1675   std::string log_data;
1676   log->FinalizeLog(truncate_events, current_app_version, std::move(close_time),
1677                    &log_data);
1678 
1679   FinalizedLog finalized_log;
1680   finalized_log.uncompressed_log_size = log_data.size();
1681   finalized_log.log_info = std::make_unique<UnsentLogStore::LogInfo>();
1682   finalized_log.log_info->Init(log_data, signing_key, log->log_metadata());
1683   return finalized_log;
1684 }
1685 
1686 }  // namespace metrics
1687