xref: /aosp_15_r20/external/cronet/components/metrics/metrics_service.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 
GetLimitedEntropyRandomizationSource()483 std::string_view MetricsService::GetLimitedEntropyRandomizationSource() {
484   return state_manager_->GetLimitedEntropyRandomizationSource();
485 }
486 
SetExternalClientId(const std::string & id)487 void MetricsService::SetExternalClientId(const std::string& id) {
488   state_manager_->SetExternalClientId(id);
489 }
490 
WasLastShutdownClean() const491 bool MetricsService::WasLastShutdownClean() const {
492   return state_manager_->clean_exit_beacon()->exited_cleanly();
493 }
494 
EnableRecording()495 void MetricsService::EnableRecording() {
496   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
497 
498   if (recording_state_ == ACTIVE)
499     return;
500   recording_state_ = ACTIVE;
501 
502   state_manager_->ForceClientIdCreation();
503   client_->SetMetricsClientId(state_manager_->client_id());
504 
505   if (!current_log_) {
506     OpenNewLog();
507   }
508 
509   delegating_provider_.OnRecordingEnabled();
510 
511   // Fill in the system profile in the log and persist it (to prefs, .pma
512   // and crashpad). This includes running the providers so that information
513   // like field trials and hardware info is provided. If Chrome crashes
514   // before this log is completed, the .pma file will have this system
515   // profile.
516   RecordCurrentEnvironment(current_log_.get(), /*complete=*/false);
517 
518   base::RemoveActionCallback(action_callback_);
519   action_callback_ = base::BindRepeating(&MetricsService::OnUserAction,
520                                          base::Unretained(this));
521   base::AddActionCallback(action_callback_);
522 
523   enablement_observers_.Notify(/*enabled=*/true);
524 }
525 
DisableRecording()526 void MetricsService::DisableRecording() {
527   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
528 
529   if (recording_state_ == INACTIVE)
530     return;
531   recording_state_ = INACTIVE;
532 
533   base::RemoveActionCallback(action_callback_);
534 
535   delegating_provider_.OnRecordingDisabled();
536 
537   base::UmaHistogramBoolean("UMA.MetricsService.PendingOngoingLogOnDisable",
538                             pending_ongoing_log_);
539   PushPendingLogsToPersistentStorage(
540       MetricsLogsEventManager::CreateReason::kServiceShutdown);
541 
542   // Because histograms may still be emitted after the last log was closed, an
543   // independent log may be created in a future session in order to report
544   // those histograms. To ensure that this independent log contains histograms
545   // that we wish to appear in every log, call OnDidCreateMetricsLog().
546   delegating_provider_.OnDidCreateMetricsLog();
547 
548   enablement_observers_.Notify(/*enabled=*/false);
549 }
550 
recording_active() const551 bool MetricsService::recording_active() const {
552   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
553   return recording_state_ == ACTIVE;
554 }
555 
reporting_active() const556 bool MetricsService::reporting_active() const {
557   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
558   return reporting_service_.reporting_active();
559 }
560 
has_unsent_logs() const561 bool MetricsService::has_unsent_logs() const {
562   return reporting_service_.metrics_log_store()->has_unsent_logs();
563 }
564 
IsMetricsReportingEnabled() const565 bool MetricsService::IsMetricsReportingEnabled() const {
566   return state_manager_->IsMetricsReportingEnabled();
567 }
568 
HandleIdleSinceLastTransmission(bool in_idle)569 void MetricsService::HandleIdleSinceLastTransmission(bool in_idle) {
570   // If there wasn't a lot of action, maybe the computer was asleep, in which
571   // case, the log transmissions should have stopped.  Here we start them up
572   // again.
573   if (!in_idle && idle_since_last_transmission_)
574     StartSchedulerIfNecessary();
575   idle_since_last_transmission_ = in_idle;
576 }
577 
OnApplicationNotIdle()578 void MetricsService::OnApplicationNotIdle() {
579   if (recording_state_ == ACTIVE)
580     HandleIdleSinceLastTransmission(false);
581 }
582 
583 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
OnAppEnterBackground(bool keep_recording_in_background)584 void MetricsService::OnAppEnterBackground(bool keep_recording_in_background) {
585   is_in_foreground_ = false;
586   reporting_service_.SetIsInForegound(false);
587   if (!keep_recording_in_background) {
588     rotation_scheduler_->Stop();
589     reporting_service_.Stop();
590   }
591 
592   state_manager_->LogHasSessionShutdownCleanly(true);
593   // Schedule a write, which happens on a different thread.
594   local_state_->CommitPendingWrite();
595 
596   // Give providers a chance to persist histograms as part of being
597   // backgrounded.
598   delegating_provider_.OnAppEnterBackground();
599 
600   // At this point, there's no way of knowing when the process will be killed,
601   // so this has to be treated similar to a shutdown, closing and persisting all
602   // logs. Unlike a shutdown, the state is primed to be ready to continue
603   // logging and uploading if the process does return.
604   if (recording_active() && !IsTooEarlyToCloseLog()) {
605     base::UmaHistogramBoolean(
606         "UMA.MetricsService.PendingOngoingLogOnBackgrounded",
607         pending_ongoing_log_);
608 #if BUILDFLAG(IS_ANDROID)
609     client_->MergeSubprocessHistograms();
610 #endif  // BUILDFLAG(IS_ANDROID)
611     {
612       ScopedTerminationChecker scoped_termination_checker(
613           "UMA.MetricsService.OnBackgroundedScopedTerminationChecker");
614       PushPendingLogsToPersistentStorage(
615           MetricsLogsEventManager::CreateReason::kBackgrounded);
616     }
617     // Persisting logs closes the current log, so start recording a new log
618     // immediately to capture any background work that might be done before the
619     // process is killed.
620     OpenNewLog();
621   }
622 }
623 
OnAppEnterForeground(bool force_open_new_log)624 void MetricsService::OnAppEnterForeground(bool force_open_new_log) {
625   is_in_foreground_ = true;
626   reporting_service_.SetIsInForegound(true);
627   state_manager_->LogHasSessionShutdownCleanly(false);
628   StartSchedulerIfNecessary();
629 
630   if (force_open_new_log && recording_active() && !IsTooEarlyToCloseLog()) {
631     base::UmaHistogramBoolean(
632         "UMA.MetricsService.PendingOngoingLogOnForegrounded",
633         pending_ongoing_log_);
634 #if BUILDFLAG(IS_ANDROID)
635     client_->MergeSubprocessHistograms();
636 #endif  // BUILDFLAG(IS_ANDROID)
637     // Because state_ >= SENDING_LOGS, PushPendingLogsToPersistentStorage()
638     // will close the log, allowing a new log to be opened.
639     PushPendingLogsToPersistentStorage(
640         MetricsLogsEventManager::CreateReason::kForegrounded);
641     OpenNewLog();
642   }
643 }
644 #endif  // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
645 
OnPageLoadStarted()646 void MetricsService::OnPageLoadStarted() {
647   delegating_provider_.OnPageLoadStarted();
648 }
649 
LogCleanShutdown()650 void MetricsService::LogCleanShutdown() {
651   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
652   state_manager_->LogHasSessionShutdownCleanly(true);
653 }
654 
ClearSavedStabilityMetrics()655 void MetricsService::ClearSavedStabilityMetrics() {
656   delegating_provider_.ClearSavedStabilityMetrics();
657   // Stability metrics are stored in Local State prefs, so schedule a Local
658   // State write to flush the updated prefs.
659   local_state_->CommitPendingWrite();
660 }
661 
MarkCurrentHistogramsAsReported()662 void MetricsService::MarkCurrentHistogramsAsReported() {
663   DiscardingFlattener flattener;
664   base::HistogramSnapshotManager snapshot_manager(&flattener);
665   base::StatisticsRecorder::PrepareDeltas(
666       /*include_persistent=*/true, /*flags_to_set=*/base::Histogram::kNoFlags,
667       /*required_flags=*/base::Histogram::kUmaTargetedHistogramFlag,
668       &snapshot_manager);
669 }
670 
671 #if BUILDFLAG(IS_CHROMEOS_ASH)
SetUserLogStore(std::unique_ptr<UnsentLogStore> user_log_store)672 void MetricsService::SetUserLogStore(
673     std::unique_ptr<UnsentLogStore> user_log_store) {
674   if (log_store()->has_alternate_ongoing_log_store())
675     return;
676 
677   if (state_ >= SENDING_LOGS) {
678     // Closes the current log so that a new log can be opened in the user log
679     // store.
680     PushPendingLogsToPersistentStorage(
681         MetricsLogsEventManager::CreateReason::kAlternateOngoingLogStoreSet);
682     log_store()->SetAlternateOngoingLogStore(std::move(user_log_store));
683     OpenNewLog();
684     RecordUserLogStoreState(kSetPostSendLogsState);
685   } else {
686     // Initial log has not yet been created and flushing now would result in
687     // incomplete information in the current log.
688     //
689     // Logs recorded before a user login will be appended to user logs. This
690     // should not happen frequently.
691     //
692     // TODO(crbug.com/40203458): Look for a way to "pause" pre-login logs and
693     // flush when INIT_TASK is done.
694     log_store()->SetAlternateOngoingLogStore(std::move(user_log_store));
695     RecordUserLogStoreState(kSetPreSendLogsState);
696   }
697 }
698 
UnsetUserLogStore()699 void MetricsService::UnsetUserLogStore() {
700   if (!log_store()->has_alternate_ongoing_log_store())
701     return;
702 
703   if (state_ >= SENDING_LOGS) {
704     PushPendingLogsToPersistentStorage(
705         MetricsLogsEventManager::CreateReason::kAlternateOngoingLogStoreUnset);
706     log_store()->UnsetAlternateOngoingLogStore();
707     OpenNewLog();
708     RecordUserLogStoreState(kUnsetPostSendLogsState);
709     return;
710   }
711 
712   // Fast startup and logout case. We flush all histograms and discard the
713   // current log. This is to prevent histograms captured during the user
714   // session from leaking into local state logs.
715   // TODO(crbug.com/40245274): Consider not flushing histograms here.
716 
717   // Discard histograms.
718   DiscardingFlattener flattener;
719   base::HistogramSnapshotManager histogram_snapshot_manager(&flattener);
720   delegating_provider_.RecordHistogramSnapshots(&histogram_snapshot_manager);
721   base::StatisticsRecorder::PrepareDeltas(
722       /*include_persistent=*/true, /*flags_to_set=*/base::Histogram::kNoFlags,
723       /*required_flags=*/base::Histogram::kUmaTargetedHistogramFlag,
724       &histogram_snapshot_manager);
725 
726   // Discard the current log and don't store it.
727   CHECK(current_log_);
728   current_log_.reset();
729 
730   log_store()->UnsetAlternateOngoingLogStore();
731   RecordUserLogStoreState(kUnsetPreSendLogsState);
732 }
733 
HasUserLogStore()734 bool MetricsService::HasUserLogStore() {
735   return log_store()->has_alternate_ongoing_log_store();
736 }
737 
InitPerUserMetrics()738 void MetricsService::InitPerUserMetrics() {
739   client_->InitPerUserMetrics();
740 }
741 
GetCurrentUserMetricsConsent() const742 std::optional<bool> MetricsService::GetCurrentUserMetricsConsent() const {
743   return client_->GetCurrentUserMetricsConsent();
744 }
745 
GetCurrentUserId() const746 std::optional<std::string> MetricsService::GetCurrentUserId() const {
747   return client_->GetCurrentUserId();
748 }
749 
UpdateCurrentUserMetricsConsent(bool user_metrics_consent)750 void MetricsService::UpdateCurrentUserMetricsConsent(
751     bool user_metrics_consent) {
752   client_->UpdateCurrentUserMetricsConsent(user_metrics_consent);
753 }
754 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
755 
756 #if BUILDFLAG(IS_CHROMEOS)
ResetClientId()757 void MetricsService::ResetClientId() {
758   // Pref must be cleared in order for ForceClientIdCreation to generate a new
759   // client ID.
760   local_state_->ClearPref(prefs::kMetricsClientID);
761   local_state_->ClearPref(prefs::kMetricsLogFinalizedRecordId);
762   local_state_->ClearPref(prefs::kMetricsLogRecordId);
763   state_manager_->ForceClientIdCreation();
764   client_->SetMetricsClientId(state_manager_->client_id());
765 }
766 #endif  // BUILDFLAG(IS_CHROMEOS)
767 
768 variations::SyntheticTrialRegistry*
GetSyntheticTrialRegistry()769 MetricsService::GetSyntheticTrialRegistry() {
770   return client_->GetSyntheticTrialRegistry();
771 }
772 
GetInitializationDelay()773 base::TimeDelta MetricsService::GetInitializationDelay() {
774   return base::Seconds(
775       client_->ShouldStartUpFastForTesting() ? 0 : kInitializationDelaySeconds);
776 }
777 
GetUpdateLastAliveTimestampDelay()778 base::TimeDelta MetricsService::GetUpdateLastAliveTimestampDelay() {
779   return base::Seconds(kUpdateAliveTimestampSeconds);
780 }
781 
StageCurrentLogForTest()782 bool MetricsService::StageCurrentLogForTest() {
783   CloseCurrentLog(/*async=*/false,
784                   MetricsLogsEventManager::CreateReason::kUnknown);
785 
786   MetricsLogStore* const log_store = reporting_service_.metrics_log_store();
787   log_store->StageNextLog();
788   if (!log_store->has_staged_log())
789     return false;
790 
791   OpenNewLog();
792   return true;
793 }
794 
795 //------------------------------------------------------------------------------
796 // private methods
797 //------------------------------------------------------------------------------
798 
799 //------------------------------------------------------------------------------
800 // Initialization methods
801 
InitializeMetricsState()802 void MetricsService::InitializeMetricsState() {
803   SCOPED_UMA_HISTOGRAM_TIMER_MICROS("UMA.MetricsService.Initialize.Time");
804 
805   const int64_t buildtime = MetricsLog::GetBuildTime();
806   const std::string version = client_->GetVersionString();
807 
808   bool version_changed = false;
809   EnvironmentRecorder recorder(local_state_);
810   int64_t previous_buildtime = recorder.GetLastBuildtime();
811   std::string previous_version = recorder.GetLastVersion();
812   if (previous_buildtime != buildtime || previous_version != version) {
813     recorder.SetBuildtimeAndVersion(buildtime, version);
814     version_changed = true;
815   }
816 
817   session_id_ = local_state_->GetInteger(prefs::kMetricsSessionID);
818 
819   StabilityMetricsProvider provider(local_state_);
820   const bool was_last_shutdown_clean = WasLastShutdownClean();
821   if (!was_last_shutdown_clean) {
822     provider.LogCrash(
823         state_manager_->clean_exit_beacon()->browser_last_live_timestamp());
824 #if BUILDFLAG(IS_ANDROID)
825     if (!state_manager_->is_foreground_session()) {
826       // Android can have background sessions in which the app may not come to
827       // the foreground, so signal that Chrome should stop watching for crashes
828       // here. This ensures that the termination of such sessions is not
829       // considered a crash. If and when the app enters the foreground, Chrome
830       // starts watching for crashes via MetricsService::OnAppEnterForeground().
831       //
832       // TODO(crbug/1232027): Such sessions do not yet exist on iOS. When they
833       // do, it may not be possible to know at this point whether a session is a
834       // background session.
835       //
836       // TODO(crbug.com/40788576): On WebLayer, it is not possible to know
837       // whether it's a background session at this point.
838       //
839       // TODO(crbug.com/40196247): Ditto for WebView.
840       state_manager_->clean_exit_beacon()->WriteBeaconValue(true);
841     }
842 #endif  // BUILDFLAG(IS_ANDROID)
843   }
844 
845   // HasPreviousSessionData is called first to ensure it is never bypassed.
846   const bool is_initial_stability_log_required =
847       delegating_provider_.HasPreviousSessionData() || !was_last_shutdown_clean;
848   bool has_initial_stability_log = false;
849   if (is_initial_stability_log_required) {
850     // If the previous session didn't exit cleanly, or if any provider
851     // explicitly requests it, prepare an initial stability log -
852     // provided UMA is enabled.
853     if (state_manager_->IsMetricsReportingEnabled()) {
854       has_initial_stability_log = PrepareInitialStabilityLog(previous_version);
855     }
856   }
857 
858   // If the version changed, but no initial stability log was generated, clear
859   // the stability stats from the previous version (so that they don't get
860   // attributed to the current version). This could otherwise happen due to a
861   // number of different edge cases, such as if the last version crashed before
862   // it could save off a system profile or if UMA reporting is disabled (which
863   // normally results in stats being accumulated).
864   if (version_changed && !has_initial_stability_log)
865     ClearSavedStabilityMetrics();
866 
867   // If the version changed, the system profile is obsolete and needs to be
868   // cleared. This is to avoid the stability data misattribution that could
869   // occur if the current version crashed before saving its own system profile.
870   // Note however this clearing occurs only after preparing the initial
871   // stability log, an operation that requires the previous version's system
872   // profile. At this point, stability metrics pertaining to the previous
873   // version have been cleared.
874   if (version_changed)
875     recorder.ClearEnvironmentFromPrefs();
876 
877   // Update session ID.
878   ++session_id_;
879   local_state_->SetInteger(prefs::kMetricsSessionID, session_id_);
880 
881   // Notify stability metrics providers about the launch.
882   provider.LogLaunch();
883 
884   // Call GetUptimes() for the first time, thus allowing all later calls
885   // to record incremental uptimes accurately.
886   base::TimeDelta ignored_uptime_parameter;
887   base::TimeDelta startup_uptime;
888   GetUptimes(local_state_, &startup_uptime, &ignored_uptime_parameter);
889   DCHECK_EQ(0, startup_uptime.InMicroseconds());
890 }
891 
OnUserAction(const std::string & action,base::TimeTicks action_time)892 void MetricsService::OnUserAction(const std::string& action,
893                                   base::TimeTicks action_time) {
894   current_log_->RecordUserAction(action, action_time);
895   HandleIdleSinceLastTransmission(false);
896 }
897 
FinishedInitTask()898 void MetricsService::FinishedInitTask() {
899   DCHECK_EQ(INIT_TASK_SCHEDULED, state_);
900   state_ = INIT_TASK_DONE;
901   rotation_scheduler_->InitTaskComplete();
902 }
903 
GetUptimes(PrefService * pref,base::TimeDelta * incremental_uptime,base::TimeDelta * uptime)904 void MetricsService::GetUptimes(PrefService* pref,
905                                 base::TimeDelta* incremental_uptime,
906                                 base::TimeDelta* uptime) {
907   base::TimeTicks now = base::TimeTicks::Now();
908   // If this is the first call, init |first_updated_time_| and
909   // |last_updated_time_|.
910   if (last_updated_time_.is_null()) {
911     first_updated_time_ = now;
912     last_updated_time_ = now;
913   }
914   *incremental_uptime = now - last_updated_time_;
915   *uptime = now - first_updated_time_;
916   last_updated_time_ = now;
917 }
918 
919 //------------------------------------------------------------------------------
920 // Recording control methods
921 
OpenNewLog(bool call_providers)922 void MetricsService::OpenNewLog(bool call_providers) {
923   CHECK(!current_log_);
924 
925   current_log_ = CreateLog(MetricsLog::ONGOING_LOG);
926   if (call_providers) {
927     delegating_provider_.OnDidCreateMetricsLog();
928   }
929 
930   DCHECK_NE(CONSTRUCTED, state_);
931   if (state_ == INITIALIZED) {
932     // We only need to schedule that run once.
933     state_ = INIT_TASK_SCHEDULED;
934 
935     base::TimeDelta initialization_delay = GetInitializationDelay();
936     base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
937         FROM_HERE,
938         base::BindOnce(&MetricsService::StartInitTask,
939                        self_ptr_factory_.GetWeakPtr()),
940         initialization_delay);
941 
942     base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
943         FROM_HERE,
944         base::BindOnce(&MetricsService::PrepareProviderMetricsTask,
945                        self_ptr_factory_.GetWeakPtr()),
946         2 * initialization_delay);
947   }
948 }
949 
950 MetricsService::FinalizedLog::FinalizedLog() = default;
951 MetricsService::FinalizedLog::~FinalizedLog() = default;
952 MetricsService::FinalizedLog::FinalizedLog(FinalizedLog&& other) = default;
953 MetricsService::FinalizedLog& MetricsService::FinalizedLog::operator=(
954     FinalizedLog&& other) = default;
955 
MetricsLogHistogramWriter(MetricsLog * log)956 MetricsService::MetricsLogHistogramWriter::MetricsLogHistogramWriter(
957     MetricsLog* log)
958     : MetricsLogHistogramWriter(log,
959                                 base::Histogram::kUmaTargetedHistogramFlag) {}
960 
MetricsLogHistogramWriter(MetricsLog * log,base::HistogramBase::Flags required_flags)961 MetricsService::MetricsLogHistogramWriter::MetricsLogHistogramWriter(
962     MetricsLog* log,
963     base::HistogramBase::Flags required_flags)
964     : required_flags_(required_flags),
965       flattener_(std::make_unique<IndependentFlattener>(log)),
966       histogram_snapshot_manager_(
967           std::make_unique<base::HistogramSnapshotManager>(flattener_.get())),
968       snapshot_transaction_id_(0) {}
969 
970 MetricsService::MetricsLogHistogramWriter::~MetricsLogHistogramWriter() =
971     default;
972 
973 void MetricsService::MetricsLogHistogramWriter::
SnapshotStatisticsRecorderDeltas()974     SnapshotStatisticsRecorderDeltas() {
975   SCOPED_UMA_HISTOGRAM_TIMER("UMA.MetricsService.SnapshotDeltasTime");
976   snapshot_transaction_id_ = base::StatisticsRecorder::PrepareDeltas(
977       /*include_persistent=*/true,
978       /*flags_to_set=*/base::Histogram::kNoFlags, required_flags_,
979       histogram_snapshot_manager_.get());
980 }
981 
982 void MetricsService::MetricsLogHistogramWriter::
SnapshotStatisticsRecorderUnloggedSamples()983     SnapshotStatisticsRecorderUnloggedSamples() {
984   snapshot_transaction_id_ = base::StatisticsRecorder::SnapshotUnloggedSamples(
985       required_flags_, histogram_snapshot_manager_.get());
986 }
987 
IndependentMetricsLoader(std::unique_ptr<MetricsLog> log,std::string app_version,std::string signing_key)988 MetricsService::IndependentMetricsLoader::IndependentMetricsLoader(
989     std::unique_ptr<MetricsLog> log,
990     std::string app_version,
991     std::string signing_key)
992     : log_(std::move(log)),
993       flattener_(new IndependentFlattener(log_.get())),
994       snapshot_manager_(new base::HistogramSnapshotManager(flattener_.get())),
995       app_version_(std::move(app_version)),
996       signing_key_(std::move(signing_key)) {
997   CHECK(log_);
998   CHECK_EQ(log_->log_type(), MetricsLog::INDEPENDENT_LOG);
999 }
1000 
1001 MetricsService::IndependentMetricsLoader::~IndependentMetricsLoader() = default;
1002 
Run(base::OnceCallback<void (bool)> done_callback,MetricsProvider * metrics_provider)1003 void MetricsService::IndependentMetricsLoader::Run(
1004     base::OnceCallback<void(bool)> done_callback,
1005     MetricsProvider* metrics_provider) {
1006   CHECK(!run_called_);
1007   run_called_ = true;
1008 
1009   metrics_provider->ProvideIndependentMetrics(
1010       // Unretained is safe because this callback is either called before
1011       // |done_callback|, or in |done_callback|. Either case is fine because
1012       // |done_callback| owns |this|.
1013       base::BindOnce(&MetricsService::IndependentMetricsLoader::FinalizeLog,
1014                      base::Unretained(this)),
1015       std::move(done_callback), log_->uma_proto(), snapshot_manager_.get());
1016 }
1017 
FinalizeLog()1018 void MetricsService::IndependentMetricsLoader::FinalizeLog() {
1019   CHECK(run_called_);
1020   CHECK(!finalize_log_called_);
1021   finalize_log_called_ = true;
1022 
1023   // Release |snapshot_manager_| and then |flattener_| to prevent dangling
1024   // pointers, since |log_| will be released in MetricsService::FinalizeLog().
1025   snapshot_manager_.reset();
1026   flattener_.reset();
1027 
1028   // Note that the close_time param must not be set for independent logs.
1029   finalized_log_ = MetricsService::FinalizeLog(
1030       std::move(log_), /*truncate_events=*/false, /*close_time=*/std::nullopt,
1031       app_version_, signing_key_);
1032 }
1033 
HasFinalizedLog()1034 bool MetricsService::IndependentMetricsLoader::HasFinalizedLog() {
1035   return finalize_log_called_ && !release_finalized_log_called_;
1036 }
1037 
1038 MetricsService::FinalizedLog
ReleaseFinalizedLog()1039 MetricsService::IndependentMetricsLoader::ReleaseFinalizedLog() {
1040   CHECK(HasFinalizedLog());
1041 
1042   release_finalized_log_called_ = true;
1043   return std::move(finalized_log_);
1044 }
1045 
StartInitTask()1046 void MetricsService::StartInitTask() {
1047   delegating_provider_.AsyncInit(base::BindOnce(
1048       &MetricsService::FinishedInitTask, self_ptr_factory_.GetWeakPtr()));
1049 }
1050 
CloseCurrentLog(bool async,MetricsLogsEventManager::CreateReason reason,base::OnceClosure log_stored_callback)1051 void MetricsService::CloseCurrentLog(
1052     bool async,
1053     MetricsLogsEventManager::CreateReason reason,
1054     base::OnceClosure log_stored_callback) {
1055   if (!current_log_) {
1056     return;
1057   }
1058 
1059   // If a persistent allocator is in use, update its internal histograms (such
1060   // as how much memory is being used) before reporting.
1061   base::PersistentHistogramAllocator* allocator =
1062       base::GlobalHistogramAllocator::Get();
1063   if (allocator)
1064     allocator->UpdateTrackingHistograms();
1065 
1066   // Put incremental data (histogram deltas, and realtime stats deltas) at the
1067   // end of all log transmissions (initial log handles this separately).
1068   // RecordIncrementalStabilityElements only exists on the derived
1069   // MetricsLog class.
1070   std::unique_ptr<MetricsLog> current_log(std::move(current_log_));
1071   RecordCurrentEnvironment(current_log.get(), /*complete=*/true);
1072   base::TimeDelta incremental_uptime;
1073   base::TimeDelta uptime;
1074   GetUptimes(local_state_, &incremental_uptime, &uptime);
1075   current_log->RecordCurrentSessionData(incremental_uptime, uptime,
1076                                         &delegating_provider_, local_state_);
1077   current_log->AssignFinalizedRecordId(local_state_);
1078 
1079   auto log_histogram_writer =
1080       std::make_unique<MetricsLogHistogramWriter>(current_log.get());
1081 
1082   // Let metrics providers provide histogram snapshots independently if they
1083   // have any. This is done synchronously.
1084   delegating_provider_.RecordHistogramSnapshots(
1085       log_histogram_writer->histogram_snapshot_manager());
1086 
1087   MetricsLog::LogType log_type = current_log->log_type();
1088   CHECK_EQ(log_type, MetricsLog::ONGOING_LOG);
1089   ChromeUserMetricsExtension::RealLocalTime close_time =
1090       current_log->GetCurrentClockTime(/*record_time_zone=*/true);
1091   std::string signing_key = log_store()->GetSigningKeyForLogType(log_type);
1092   std::string current_app_version = client_->GetVersionString();
1093 
1094 #if !BUILDFLAG(IS_ANDROID)
1095   if (base::FeatureList::IsEnabled(
1096           features::kMetricsServiceDeltaSnapshotInBg)) {
1097     // If this is an async periodic log, and the browser is about to be shut
1098     // down (determined by KeepAliveRegistry::IsShuttingDown(), indicating that
1099     // there is nothing else to keep the browser alive), then do the work
1100     // synchronously instead. Otherwise, creating a ScopedKeepAlive below while
1101     // the KeepAliveRegistry has already started shutting down will trigger a
1102     // CHECK. Alternatively, the ScopedKeepAlive below could be omitted when the
1103     // KeepAliveRegistry is shutting down, but since the browser is shutting
1104     // down soon, then it is likely that the asynchronous task to close the
1105     // current the log will be cut short, causing data loss.
1106     if (async && KeepAliveRegistry::GetInstance()->IsShuttingDown()) {
1107       async = false;
1108     }
1109   }
1110 #endif
1111 
1112   if (async) {
1113     if (base::FeatureList::IsEnabled(
1114             features::kMetricsServiceDeltaSnapshotInBg)) {
1115       // In this mode, we perform the full "delta snapshot" (snapshotting
1116       // unlogged samples and marking them as logged) in the background, in
1117       // contrast to snapshotting unlogged samples in the background and marking
1118       // them as logged when back on the main thread, as is done in the else
1119       // branch.
1120 
1121       auto background_task = base::BindOnce(
1122           &MetricsService::SnapshotDeltasAndFinalizeLog,
1123           std::move(log_histogram_writer), std::move(current_log),
1124           /*truncate_events=*/true, std::move(close_time),
1125           std::move(current_app_version), std::move(signing_key));
1126       auto reply_task = base::BindOnce(&MetricsService::StoreFinalizedLog,
1127                                        self_ptr_factory_.GetWeakPtr(), log_type,
1128                                        reason, std::move(log_stored_callback));
1129 
1130 #if !BUILDFLAG(IS_ANDROID)
1131       // Prevent the browser from shutting down while creating the log in the
1132       // background. This is done by creating a ScopedKeepAlive that is only
1133       // destroyed after the log has been stored. Not used on Android because it
1134       // has no shutdown code path.
1135       reply_task = std::move(reply_task)
1136                        .Then(base::BindOnce(
1137                            [](std::unique_ptr<ScopedKeepAlive>) {
1138                              // This function does nothing but keep the
1139                              // ScopedKeepAlive param alive until we have
1140                              // finished storing the log.
1141                            },
1142                            std::make_unique<ScopedKeepAlive>(
1143                                KeepAliveOrigin::UMA_LOG,
1144                                KeepAliveRestartOption::DISABLED)));
1145 #endif  // !BUILDFLAG(IS_ANDROID)
1146 
1147       base::ThreadPool::PostTaskAndReplyWithResult(
1148           FROM_HERE,
1149           {base::TaskPriority::USER_BLOCKING,
1150            base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
1151           std::move(background_task), std::move(reply_task));
1152     } else {
1153       // To finalize the log asynchronously, we snapshot the unlogged samples of
1154       // histograms and fill them into the log, without actually marking the
1155       // samples as logged. We only mark them as logged after running the main
1156       // thread reply task to store the log. This way, we will not lose the
1157       // samples in case Chrome closes while the background task is running.
1158       // Note that while this async log is being finalized, it is possible that
1159       // another log is finalized and stored synchronously, which could
1160       // potentially cause the same samples to be in two different logs, and
1161       // hence sent twice. To prevent this, if a synchronous log is stored while
1162       // the async one is being finalized, we discard the async log as it would
1163       // be a subset of the synchronous one (in terms of histograms). For more
1164       // details, see MaybeCleanUpAndStoreFinalizedLog().
1165       //
1166       // TODO(crbug/1052796): Find a way to save the other data such as user
1167       // actions and omnibox events when we discard an async log.
1168       MetricsLogHistogramWriter* log_histogram_writer_ptr =
1169           log_histogram_writer.get();
1170       base::ThreadPool::PostTaskAndReplyWithResult(
1171           FROM_HERE,
1172           // CONTINUE_ON_SHUTDOWN because the work done is only useful once the
1173           // reply task is run (and there are no side effects). So, no need to
1174           // block shutdown since the reply task won't be run anyway.
1175           // NOTE: If attempting to change the USER_BLOCKING priority, do a
1176           // study on the impact first since it might affect the number of logs
1177           // being uploaded (which might have secondary effects, e.g. on metrics
1178           // that rely on number of logs uploaded).
1179           {base::TaskPriority::USER_BLOCKING,
1180            base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
1181           base::BindOnce(&MetricsService::SnapshotUnloggedSamplesAndFinalizeLog,
1182                          log_histogram_writer_ptr, std::move(current_log),
1183                          /*truncate_events=*/true, std::move(close_time),
1184                          std::move(current_app_version),
1185                          std::move(signing_key)),
1186           base::BindOnce(&MetricsService::MaybeCleanUpAndStoreFinalizedLog,
1187                          self_ptr_factory_.GetWeakPtr(),
1188                          std::move(log_histogram_writer), log_type, reason,
1189                          std::move(log_stored_callback)));
1190       async_ongoing_log_posted_time_ = base::TimeTicks::Now();
1191     }
1192   } else {
1193     FinalizedLog finalized_log = SnapshotDeltasAndFinalizeLog(
1194         std::move(log_histogram_writer), std::move(current_log),
1195         /*truncate_events=*/true, std::move(close_time),
1196         std::move(current_app_version), std::move(signing_key));
1197     StoreFinalizedLog(log_type, reason, std::move(log_stored_callback),
1198                       std::move(finalized_log));
1199   }
1200 }
1201 
StoreFinalizedLog(MetricsLog::LogType log_type,MetricsLogsEventManager::CreateReason reason,base::OnceClosure done_callback,FinalizedLog finalized_log)1202 void MetricsService::StoreFinalizedLog(
1203     MetricsLog::LogType log_type,
1204     MetricsLogsEventManager::CreateReason reason,
1205     base::OnceClosure done_callback,
1206     FinalizedLog finalized_log) {
1207   log_store()->StoreLogInfo(std::move(finalized_log.log_info),
1208                             finalized_log.uncompressed_log_size, log_type,
1209                             reason);
1210   std::move(done_callback).Run();
1211 }
1212 
MaybeCleanUpAndStoreFinalizedLog(std::unique_ptr<MetricsLogHistogramWriter> log_histogram_writer,MetricsLog::LogType log_type,MetricsLogsEventManager::CreateReason reason,base::OnceClosure done_callback,FinalizedLog finalized_log)1213 void MetricsService::MaybeCleanUpAndStoreFinalizedLog(
1214     std::unique_ptr<MetricsLogHistogramWriter> log_histogram_writer,
1215     MetricsLog::LogType log_type,
1216     MetricsLogsEventManager::CreateReason reason,
1217     base::OnceClosure done_callback,
1218     FinalizedLog finalized_log) {
1219   UMA_HISTOGRAM_TIMES("UMA.MetricsService.PeriodicOngoingLog.ReplyTime",
1220                       base::TimeTicks::Now() - async_ongoing_log_posted_time_);
1221 
1222   // Store the finalized log only if the StatisticRecorder's last transaction ID
1223   // is the same as the one from |log_histogram_writer|. If they are not the
1224   // same, then it indicates that another log was created while creating
1225   // |finalized_log| (that log would be a superset of |finalized_log| in terms
1226   // of histograms, so we discard |finalized_log| by not storing it).
1227   //
1228   // TODO(crbug/1052796): Find a way to save the other data such as user actions
1229   // and omnibox events when we discard |finalized_log|.
1230   //
1231   // Note that the call to StatisticsRecorder::GetLastSnapshotTransactionId()
1232   // here should not have to wait for a lock since there should not be any async
1233   // logs being created (|rotation_scheduler_| is only re-scheduled at the end
1234   // of this method).
1235   bool should_store_log =
1236       (base::StatisticsRecorder::GetLastSnapshotTransactionId() ==
1237        log_histogram_writer->snapshot_transaction_id());
1238   base::UmaHistogramBoolean("UMA.MetricsService.ShouldStoreAsyncLog",
1239                             should_store_log);
1240 
1241   if (!should_store_log) {
1242     // We still need to run |done_callback| even if we do not store the log.
1243     std::move(done_callback).Run();
1244     return;
1245   }
1246 
1247   SCOPED_UMA_HISTOGRAM_TIMER(
1248       "UMA.MetricsService.MaybeCleanUpAndStoreFinalizedLog.Time");
1249 
1250   log_histogram_writer->histogram_snapshot_manager()
1251       ->MarkUnloggedSamplesAsLogged();
1252   StoreFinalizedLog(log_type, reason, std::move(done_callback),
1253                     std::move(finalized_log));
1254 }
1255 
PushPendingLogsToPersistentStorage(MetricsLogsEventManager::CreateReason reason)1256 void MetricsService::PushPendingLogsToPersistentStorage(
1257     MetricsLogsEventManager::CreateReason reason) {
1258   if (IsTooEarlyToCloseLog()) {
1259     return;
1260   }
1261 
1262   base::UmaHistogramBoolean("UMA.MetricsService.PendingOngoingLog",
1263                             pending_ongoing_log_);
1264 
1265   // Close and store a log synchronously because this is usually called in
1266   // critical code paths (e.g., shutdown) where we may not have time to run
1267   // background tasks.
1268   CloseCurrentLog(/*async=*/false, reason);
1269   log_store()->TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
1270 }
1271 
1272 //------------------------------------------------------------------------------
1273 // Transmission of logs methods
1274 
StartSchedulerIfNecessary()1275 void MetricsService::StartSchedulerIfNecessary() {
1276   // Never schedule cutting or uploading of logs in test mode.
1277   if (test_mode_active_)
1278     return;
1279 
1280   // Even if reporting is disabled, the scheduler is needed to trigger the
1281   // creation of the first ongoing log, which must be done in order for any logs
1282   // to be persisted on shutdown or backgrounding.
1283   if (recording_active() && (reporting_active() || state_ < SENDING_LOGS)) {
1284     rotation_scheduler_->Start();
1285     reporting_service_.Start();
1286   }
1287 }
1288 
StartScheduledUpload()1289 void MetricsService::StartScheduledUpload() {
1290   DVLOG(1) << "StartScheduledUpload";
1291   DCHECK(state_ >= INIT_TASK_DONE);
1292 
1293   // If we're getting no notifications, then the log won't have much in it, and
1294   // it's possible the computer is about to go to sleep, so don't upload and
1295   // stop the scheduler.
1296   // If recording has been turned off, the scheduler doesn't need to run.
1297   // If reporting is off, proceed if the first ongoing log hasn't been created,
1298   // since that has to happen in order for logs to be cut and stored when
1299   // persisting.
1300   // TODO(stuartmorgan): Call Stop() on the scheduler when reporting and/or
1301   // recording are turned off instead of letting it fire and then aborting.
1302   if (idle_since_last_transmission_ || !recording_active() ||
1303       (!reporting_active() && state_ >= SENDING_LOGS)) {
1304     rotation_scheduler_->Stop();
1305     rotation_scheduler_->RotationFinished();
1306     return;
1307   }
1308 
1309   // The first ongoing log should be collected prior to sending any unsent logs.
1310   if (state_ == INIT_TASK_DONE) {
1311     client_->CollectFinalMetricsForLog(
1312         base::BindOnce(&MetricsService::OnFinalLogInfoCollectionDone,
1313                        self_ptr_factory_.GetWeakPtr()));
1314     return;
1315   }
1316 
1317   // If there are unsent logs, send the next one. If not, start the asynchronous
1318   // process of finalizing the current log for upload.
1319   if (has_unsent_logs()) {
1320     reporting_service_.Start();
1321     rotation_scheduler_->RotationFinished();
1322   } else {
1323     // There are no logs left to send, so start creating a new one.
1324     client_->CollectFinalMetricsForLog(
1325         base::BindOnce(&MetricsService::OnFinalLogInfoCollectionDone,
1326                        self_ptr_factory_.GetWeakPtr()));
1327   }
1328 }
1329 
OnFinalLogInfoCollectionDone()1330 void MetricsService::OnFinalLogInfoCollectionDone() {
1331   DVLOG(1) << "OnFinalLogInfoCollectionDone";
1332   DCHECK(state_ >= INIT_TASK_DONE);
1333   state_ = SENDING_LOGS;
1334 
1335   // Abort if metrics were turned off during the final info gathering.
1336   if (!recording_active()) {
1337     rotation_scheduler_->Stop();
1338     rotation_scheduler_->RotationFinished();
1339     return;
1340   }
1341 
1342   SCOPED_UMA_HISTOGRAM_TIMER("UMA.MetricsService.PeriodicOngoingLog.CloseTime");
1343 
1344   // There shouldn't be two periodic ongoing logs being finalized in the
1345   // background simultaneously. This is currently enforced because:
1346   // 1. Only periodic ongoing logs are finalized asynchronously (i.e., logs
1347   //    created by the MetricsRotationScheduler).
1348   // 2. We only re-schedule the MetricsRotationScheduler after storing a
1349   //    periodic ongoing log.
1350   //
1351   // TODO(crbug/1052796): Consider making it possible to have multiple
1352   // simultaneous async logs by having some queueing system (e.g., if we want
1353   // the log created when foregrounding Chrome to be async).
1354   DCHECK(!pending_ongoing_log_);
1355   pending_ongoing_log_ = true;
1356 
1357   base::OnceClosure log_stored_callback =
1358       base::BindOnce(&MetricsService::OnAsyncPeriodicOngoingLogStored,
1359                      self_ptr_factory_.GetWeakPtr());
1360   CloseCurrentLog(/*async=*/true,
1361                   MetricsLogsEventManager::CreateReason::kPeriodic,
1362                   std::move(log_stored_callback));
1363   OpenNewLog(/*call_providers=*/false);
1364 }
1365 
OnAsyncPeriodicOngoingLogStored()1366 void MetricsService::OnAsyncPeriodicOngoingLogStored() {
1367   pending_ongoing_log_ = false;
1368 
1369   // Call OnDidCreateMetricsLog() after storing a log instead of directly after
1370   // opening a log. Otherwise, the async log that was created would potentially
1371   // have mistakenly snapshotted the histograms intended for the newly opened
1372   // log.
1373   delegating_provider_.OnDidCreateMetricsLog();
1374 
1375   // Trim and store unsent logs, including the log that was just closed, so that
1376   // they're not lost in case of a crash before upload time. However, the
1377   // in-memory log store is unchanged. I.e., logs that are trimmed will still be
1378   // available in memory. This is to give the log that was just created a chance
1379   // to be sent in case it is trimmed. After uploading (whether successful or
1380   // not), the log store is trimmed and stored again, and at that time, the
1381   // in-memory log store will be updated.
1382   log_store()->TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/false);
1383 
1384   // Do not re-schedule if metrics were turned off while finalizing the log.
1385   if (!recording_active()) {
1386     rotation_scheduler_->Stop();
1387     rotation_scheduler_->RotationFinished();
1388   } else {
1389     // Only re-schedule |rotation_scheduler_| *after* the log was stored to
1390     // ensure that only one log is created asynchronously at a time.
1391     reporting_service_.Start();
1392     rotation_scheduler_->RotationFinished();
1393     HandleIdleSinceLastTransmission(true);
1394   }
1395 }
1396 
PrepareInitialStabilityLog(const std::string & prefs_previous_version)1397 bool MetricsService::PrepareInitialStabilityLog(
1398     const std::string& prefs_previous_version) {
1399   DCHECK_EQ(CONSTRUCTED, state_);
1400 
1401   constexpr MetricsLog::LogType log_type = MetricsLog::INITIAL_STABILITY_LOG;
1402   std::unique_ptr<MetricsLog> initial_stability_log = CreateLog(log_type);
1403 
1404   // Do not call OnDidCreateMetricsLog here because the stability log describes
1405   // stats from the _previous_ session.
1406 
1407   if (!initial_stability_log->LoadSavedEnvironmentFromPrefs(local_state_))
1408     return false;
1409 
1410   initial_stability_log->RecordPreviousSessionData(&delegating_provider_,
1411                                                    local_state_);
1412   initial_stability_log->AssignFinalizedRecordId(local_state_);
1413 
1414   auto log_histogram_writer = std::make_unique<MetricsLogHistogramWriter>(
1415       initial_stability_log.get(), base::Histogram::kUmaStabilityHistogramFlag);
1416 
1417   // Add a beacon to this record to indicate that it's part of the initial
1418   // stability log.
1419   UMA_STABILITY_HISTOGRAM_BOOLEAN("UMA.InitialStabilityRecordBeacon", true);
1420 
1421   // Let metrics providers provide histogram snapshots independently if they
1422   // have any. This is done synchronously.
1423   delegating_provider_.RecordInitialHistogramSnapshots(
1424       log_histogram_writer->histogram_snapshot_manager());
1425 
1426   std::string signing_key = log_store()->GetSigningKeyForLogType(log_type);
1427 
1428   // Synchronously create the initial stability log in order to ensure that the
1429   // stability histograms are filled into this specific log. Note that the
1430   // close_time param must not be set for initial stability logs.
1431   FinalizedLog finalized_log = SnapshotDeltasAndFinalizeLog(
1432       std::move(log_histogram_writer), std::move(initial_stability_log),
1433       /*truncate_events=*/false, /*close_time=*/std::nullopt,
1434       client_->GetVersionString(), std::move(signing_key));
1435   StoreFinalizedLog(log_type, MetricsLogsEventManager::CreateReason::kStability,
1436                     base::DoNothing(), std::move(finalized_log));
1437 
1438   // Store unsent logs, including the stability log that was just saved, so
1439   // that they're not lost in case of a crash before upload time.
1440   log_store()->TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
1441 
1442   return true;
1443 }
1444 
RegisterMetricsProvider(std::unique_ptr<MetricsProvider> provider)1445 void MetricsService::RegisterMetricsProvider(
1446     std::unique_ptr<MetricsProvider> provider) {
1447   DCHECK_EQ(CONSTRUCTED, state_);
1448   delegating_provider_.RegisterMetricsProvider(std::move(provider));
1449 }
1450 
CheckForClonedInstall()1451 void MetricsService::CheckForClonedInstall() {
1452   state_manager_->CheckForClonedInstall();
1453 }
1454 
ShouldResetClientIdsOnClonedInstall()1455 bool MetricsService::ShouldResetClientIdsOnClonedInstall() {
1456   return state_manager_->ShouldResetClientIdsOnClonedInstall();
1457 }
1458 
CreateLog(MetricsLog::LogType log_type)1459 std::unique_ptr<MetricsLog> MetricsService::CreateLog(
1460     MetricsLog::LogType log_type) {
1461   auto new_metrics_log = std::make_unique<MetricsLog>(
1462       state_manager_->client_id(), session_id_, log_type, client_);
1463   new_metrics_log->AssignRecordId(local_state_);
1464 
1465 #if BUILDFLAG(IS_CHROMEOS_ASH)
1466   std::optional<std::string> user_id = GetCurrentUserId();
1467   if (user_id.has_value())
1468     new_metrics_log->SetUserId(user_id.value());
1469 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
1470 
1471   return new_metrics_log;
1472 }
1473 
AddLogsObserver(MetricsLogsEventManager::Observer * observer)1474 void MetricsService::AddLogsObserver(
1475     MetricsLogsEventManager::Observer* observer) {
1476   logs_event_manager_.AddObserver(observer);
1477 }
1478 
RemoveLogsObserver(MetricsLogsEventManager::Observer * observer)1479 void MetricsService::RemoveLogsObserver(
1480     MetricsLogsEventManager::Observer* observer) {
1481   logs_event_manager_.RemoveObserver(observer);
1482 }
1483 
AddEnablementObserver(const base::RepeatingCallback<void (bool)> & observer)1484 base::CallbackListSubscription MetricsService::AddEnablementObserver(
1485     const base::RepeatingCallback<void(bool)>& observer) {
1486   return enablement_observers_.Add(observer);
1487 }
1488 
SetPersistentSystemProfile(const std::string & serialized_proto,bool complete)1489 void MetricsService::SetPersistentSystemProfile(
1490     const std::string& serialized_proto,
1491     bool complete) {
1492   GlobalPersistentSystemProfile::GetInstance()->SetSystemProfile(
1493       serialized_proto, complete);
1494 }
1495 
1496 // static
RecordCurrentEnvironmentHelper(MetricsLog * log,PrefService * local_state,DelegatingProvider * delegating_provider)1497 std::string MetricsService::RecordCurrentEnvironmentHelper(
1498     MetricsLog* log,
1499     PrefService* local_state,
1500     DelegatingProvider* delegating_provider) {
1501   const SystemProfileProto& system_profile =
1502       log->RecordEnvironment(delegating_provider);
1503   EnvironmentRecorder recorder(local_state);
1504   return recorder.SerializeAndRecordEnvironmentToPrefs(system_profile);
1505 }
1506 
RecordCurrentEnvironment(MetricsLog * log,bool complete)1507 void MetricsService::RecordCurrentEnvironment(MetricsLog* log, bool complete) {
1508   DCHECK(client_);
1509   std::string serialized_proto =
1510       RecordCurrentEnvironmentHelper(log, local_state_, &delegating_provider_);
1511 
1512   SetPersistentSystemProfile(serialized_proto, complete);
1513   client_->OnEnvironmentUpdate(&serialized_proto);
1514 
1515   // The call to SetPersistentSystemProfile() above will have written the
1516   // current system profile to persistent memory. Because it may span over
1517   // multiple pages, it is possible that the system profile may become corrupted
1518   // if only certain pages were flushed to disk. For example, say we overwrite
1519   // the persistent memory's system profile with a newer one, and that it spans
1520   // over two pages. Then, the OS flushes the second page, but not the first
1521   // page. If the device is shut down unexpectedly, e.g. due to a power outage,
1522   // then the first page will contain the beginning of the old system profile,
1523   // while the second page will contain the ending of the new system profile,
1524   // resulting in an unparsable system profile and rendering the whole file
1525   // useless. So, manually schedule a flush every time we overwrite the system
1526   // profile with a new one to ensure we don't ever get a corrupted one.
1527   if (base::FeatureList::IsEnabled(
1528           features::kFlushPersistentSystemProfileOnWrite)) {
1529     base::ThreadPool::PostTask(
1530         FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
1531         base::BindOnce([]() {
1532           if (auto* allocator = base::GlobalHistogramAllocator::Get()) {
1533             // Ideally, we'd just call Flush() with the |sync| parameter set to
1534             // false on the main thread, but Windows does not support async
1535             // flushing, so do this synchronously on a background thread
1536             // instead.
1537             allocator->memory_allocator()->Flush(/*sync=*/true);
1538           }
1539         }));
1540   }
1541 }
1542 
PrepareProviderMetricsLogDone(std::unique_ptr<IndependentMetricsLoader> loader,bool success)1543 void MetricsService::PrepareProviderMetricsLogDone(
1544     std::unique_ptr<IndependentMetricsLoader> loader,
1545     bool success) {
1546   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1547   DCHECK(independent_loader_active_);
1548   DCHECK(loader);
1549 
1550   if (success) {
1551     // If not already done, finalize the log that was created independently by
1552     // the metrics provider.
1553     if (!loader->HasFinalizedLog()) {
1554       loader->FinalizeLog();
1555     }
1556 
1557     StoreFinalizedLog(MetricsLog::INDEPENDENT_LOG,
1558                       MetricsLogsEventManager::CreateReason::kIndependent,
1559                       /*done_callback=*/base::DoNothing(),
1560                       loader->ReleaseFinalizedLog());
1561   }
1562 
1563   independent_loader_active_ = false;
1564 }
1565 
PrepareProviderMetricsLog()1566 bool MetricsService::PrepareProviderMetricsLog() {
1567   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1568 
1569   // If something is still pending, stop now and indicate that there is
1570   // still work to do.
1571   if (independent_loader_active_)
1572     return true;
1573 
1574   // Check each provider in turn for data.
1575   for (auto& provider : delegating_provider_.GetProviders()) {
1576     if (provider->HasIndependentMetrics()) {
1577       // Create a new log. This will have some default values injected in it
1578       // but those will be overwritten when an embedded profile is extracted.
1579       constexpr MetricsLog::LogType log_type = MetricsLog::INDEPENDENT_LOG;
1580       std::unique_ptr<MetricsLog> log = CreateLog(log_type);
1581       log->AssignFinalizedRecordId(local_state_);
1582 
1583       // Note that something is happening. This must be set before the
1584       // operation is requested in case the loader decides to do everything
1585       // immediately rather than as a background task.
1586       independent_loader_active_ = true;
1587 
1588       // Give the new log to a loader for management and then run it on the
1589       // provider that has something to give. A copy of the pointer is needed
1590       // because the unique_ptr may get moved before the value can be used
1591       // to call Run().
1592       std::unique_ptr<IndependentMetricsLoader> loader =
1593           std::make_unique<IndependentMetricsLoader>(
1594               std::move(log), client_->GetVersionString(),
1595               log_store()->GetSigningKeyForLogType(log_type));
1596       IndependentMetricsLoader* loader_ptr = loader.get();
1597       loader_ptr->Run(
1598           base::BindOnce(&MetricsService::PrepareProviderMetricsLogDone,
1599                          self_ptr_factory_.GetWeakPtr(), std::move(loader)),
1600           provider.get());
1601 
1602       // Something was found so there may still be more work to do.
1603       return true;
1604     }
1605   }
1606 
1607   // Nothing was found so indicate there is no more work to do.
1608   return false;
1609 }
1610 
PrepareProviderMetricsTask()1611 void MetricsService::PrepareProviderMetricsTask() {
1612   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1613   bool found = PrepareProviderMetricsLog();
1614   base::TimeDelta next_check = found ? base::Seconds(5) : base::Minutes(15);
1615   base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
1616       FROM_HERE,
1617       base::BindOnce(&MetricsService::PrepareProviderMetricsTask,
1618                      self_ptr_factory_.GetWeakPtr()),
1619       next_check);
1620 }
1621 
UpdateLastLiveTimestampTask()1622 void MetricsService::UpdateLastLiveTimestampTask() {
1623   state_manager_->clean_exit_beacon()->UpdateLastLiveTimestamp();
1624 
1625   // Schecule the next update.
1626   StartUpdatingLastLiveTimestamp();
1627 }
1628 
IsTooEarlyToCloseLog()1629 bool MetricsService::IsTooEarlyToCloseLog() {
1630   // When kMetricsServiceAllowEarlyLogClose is enabled, start closing logs as
1631   // soon as the first log is opened (|state_| is set to INIT_TASK_SCHEDULED
1632   // when the first log is opened, see OpenNewLog()). Otherwise, only start
1633   // closing logs when logs have started being sent.
1634   return base::FeatureList::IsEnabled(
1635              features::kMetricsServiceAllowEarlyLogClose)
1636              ? state_ < INIT_TASK_SCHEDULED
1637              : state_ < SENDING_LOGS;
1638 }
1639 
OnClonedInstallDetected()1640 void MetricsService::OnClonedInstallDetected() {
1641   // Purge all logs, as they may come from a previous install. Unfortunately,
1642   // since the cloned install detector works asynchronously, it is possible that
1643   // this is called after logs were already sent. However, practically speaking,
1644   // this should not happen, since logs are only sent late into the session.
1645   reporting_service_.metrics_log_store()->Purge();
1646 }
1647 
1648 // static
SnapshotDeltasAndFinalizeLog(std::unique_ptr<MetricsLogHistogramWriter> log_histogram_writer,std::unique_ptr<MetricsLog> log,bool truncate_events,std::optional<ChromeUserMetricsExtension::RealLocalTime> close_time,std::string && current_app_version,std::string && signing_key)1649 MetricsService::FinalizedLog MetricsService::SnapshotDeltasAndFinalizeLog(
1650     std::unique_ptr<MetricsLogHistogramWriter> log_histogram_writer,
1651     std::unique_ptr<MetricsLog> log,
1652     bool truncate_events,
1653     std::optional<ChromeUserMetricsExtension::RealLocalTime> close_time,
1654     std::string&& current_app_version,
1655     std::string&& signing_key) {
1656   log_histogram_writer->SnapshotStatisticsRecorderDeltas();
1657   return FinalizeLog(std::move(log), truncate_events, std::move(close_time),
1658                      current_app_version, signing_key);
1659 }
1660 
1661 // static
1662 MetricsService::FinalizedLog
SnapshotUnloggedSamplesAndFinalizeLog(MetricsLogHistogramWriter * log_histogram_writer,std::unique_ptr<MetricsLog> log,bool truncate_events,std::optional<ChromeUserMetricsExtension::RealLocalTime> close_time,std::string && current_app_version,std::string && signing_key)1663 MetricsService::SnapshotUnloggedSamplesAndFinalizeLog(
1664     MetricsLogHistogramWriter* log_histogram_writer,
1665     std::unique_ptr<MetricsLog> log,
1666     bool truncate_events,
1667     std::optional<ChromeUserMetricsExtension::RealLocalTime> close_time,
1668     std::string&& current_app_version,
1669     std::string&& signing_key) {
1670   log_histogram_writer->SnapshotStatisticsRecorderUnloggedSamples();
1671   return FinalizeLog(std::move(log), truncate_events, std::move(close_time),
1672                      current_app_version, signing_key);
1673 }
1674 
1675 // static
FinalizeLog(std::unique_ptr<MetricsLog> log,bool truncate_events,std::optional<ChromeUserMetricsExtension::RealLocalTime> close_time,const std::string & current_app_version,const std::string & signing_key)1676 MetricsService::FinalizedLog MetricsService::FinalizeLog(
1677     std::unique_ptr<MetricsLog> log,
1678     bool truncate_events,
1679     std::optional<ChromeUserMetricsExtension::RealLocalTime> close_time,
1680     const std::string& current_app_version,
1681     const std::string& signing_key) {
1682   DCHECK(log->uma_proto()->has_record_id());
1683   std::string log_data;
1684   log->FinalizeLog(truncate_events, current_app_version, std::move(close_time),
1685                    &log_data);
1686 
1687   FinalizedLog finalized_log;
1688   finalized_log.uncompressed_log_size = log_data.size();
1689   finalized_log.log_info = std::make_unique<UnsentLogStore::LogInfo>();
1690   finalized_log.log_info->Init(log_data, signing_key, log->log_metadata());
1691   return finalized_log;
1692 }
1693 
1694 }  // namespace metrics
1695