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