xref: /aosp_15_r20/external/cronet/components/metrics/metrics_log.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // This file defines a set of user experience metrics data recorded by the
6 // MetricsService. This is the unit of data that is sent to the server.
7 
8 #ifndef COMPONENTS_METRICS_METRICS_LOG_H_
9 #define COMPONENTS_METRICS_METRICS_LOG_H_
10 
11 #include <stdint.h>
12 
13 #include <memory>
14 #include <optional>
15 #include <string>
16 
17 #include "base/functional/callback_forward.h"
18 #include "base/memory/raw_ptr.h"
19 #include "base/metrics/histogram_base.h"
20 #include "base/strings/string_piece.h"
21 #include "base/time/time.h"
22 #include "build/chromeos_buildflags.h"
23 #include "components/metrics/metrics_reporting_default_state.h"
24 #include "third_party/metrics_proto/chrome_user_metrics_extension.pb.h"
25 #include "third_party/metrics_proto/system_profile.pb.h"
26 
27 class PrefService;
28 
29 namespace base {
30 class Clock;
31 class HistogramSamples;
32 }  // namespace base
33 
34 namespace network_time {
35 class NetworkTimeTracker;
36 }  // namespace network_time
37 
38 namespace metrics {
39 
40 // This SourceType is saved in Local state by unsent_log_store.cc and entries
41 // should not be renumbered.
42 enum UkmLogSourceType {
43   UKM_ONLY = 0,            // Log contains only UKM data.
44   APPKM_ONLY = 1,          // Log contains only AppKM data.
45   BOTH_UKM_AND_APPKM = 2,  // Log contains both AppKM and UKM data.
46 };
47 
48 // Holds optional metadata associated with a log to be stored.
49 struct LogMetadata {
50   LogMetadata();
51   LogMetadata(std::optional<base::HistogramBase::Count> samples_count,
52               std::optional<uint64_t> user_id,
53               std::optional<UkmLogSourceType> log_source_type);
54   LogMetadata(const LogMetadata& other);
55   ~LogMetadata();
56 
57   // Adds |sample_count| to |samples_count|. If |samples_count| is empty, then
58   // |sample_count| will populate |samples_count|.
59   void AddSampleCount(base::HistogramBase::Count sample_count);
60 
61   // The total number of samples in this log if applicable.
62   std::optional<base::HistogramBase::Count> samples_count;
63 
64   // User id associated with the log.
65   std::optional<uint64_t> user_id;
66 
67   // For UKM logs, indicates the type of data.
68   std::optional<UkmLogSourceType> log_source_type;
69 };
70 
71 class MetricsServiceClient;
72 class DelegatingProvider;
73 
74 namespace internal {
75 // Maximum number of events before truncation.
76 constexpr int kOmniboxEventLimit = 5000;
77 constexpr int kUserActionEventLimit = 5000;
78 
79 SystemProfileProto::InstallerPackage ToInstallerPackage(
80     base::StringPiece installer_package_name);
81 }  // namespace internal
82 
83 class MetricsLog {
84  public:
85   enum LogType {
86     INITIAL_STABILITY_LOG,  // The initial log containing stability stats.
87     ONGOING_LOG,            // Subsequent logs in a session.
88     INDEPENDENT_LOG,        // An independent log from a previous session.
89   };
90 
91   // Creates a new metrics log of the specified type.
92   // |client_id| is the identifier for this profile on this installation
93   // |session_id| is an integer that's incremented on each application launch
94   // |client| is used to interact with the embedder.
95   // Note: |this| instance does not take ownership of the |client|, but rather
96   // stores a weak pointer to it. The caller should ensure that the |client| is
97   // valid for the lifetime of this class.
98   MetricsLog(const std::string& client_id,
99              int session_id,
100              LogType log_type,
101              MetricsServiceClient* client);
102   // As above, with a |clock| and |network_clock| to use to vend Now() calls. As
103   // with |client|, the caller must ensure both remain valid for the lifetime of
104   // this class.
105   MetricsLog(const std::string& client_id,
106              int session_id,
107              LogType log_type,
108              base::Clock* clock,
109              const network_time::NetworkTimeTracker* network_clock,
110              MetricsServiceClient* client);
111 
112   MetricsLog(const MetricsLog&) = delete;
113   MetricsLog& operator=(const MetricsLog&) = delete;
114   virtual ~MetricsLog();
115 
116   // Registers local state prefs used by this class.
117   static void RegisterPrefs(PrefRegistrySimple* registry);
118 
119   // Computes the MD5 hash of the given string, and returns the first 8 bytes of
120   // the hash.
121   static uint64_t Hash(const std::string& value);
122 
123   // Get the GMT buildtime for the current binary, expressed in seconds since
124   // January 1, 1970 GMT.
125   // The value is used to identify when a new build is run, so that previous
126   // reliability stats, from other builds, can be abandoned.
127   static int64_t GetBuildTime();
128 
129   // Convenience function to return the current time at a resolution in seconds.
130   // This wraps base::TimeTicks, and hence provides an abstract time that is
131   // always incrementing for use in measuring time durations.
132   static int64_t GetCurrentTime();
133 
134   // Records core profile settings into the SystemProfileProto.
135   static void RecordCoreSystemProfile(MetricsServiceClient* client,
136                                       SystemProfileProto* system_profile);
137 
138   // Records core profile settings into the SystemProfileProto without a client.
139   static void RecordCoreSystemProfile(
140       const std::string& version,
141       metrics::SystemProfileProto::Channel channel,
142       bool is_extended_stable_channel,
143       const std::string& application_locale,
144       const std::string& package_name,
145       SystemProfileProto* system_profile);
146 
147   // Assign a unique finalized record id to this log.
148   void AssignFinalizedRecordId(PrefService* local_state);
149 
150   // Assign a unique record id to this log.
151   void AssignRecordId(PrefService* local_state);
152 
153   // Records a user-initiated action.
154   void RecordUserAction(const std::string& key, base::TimeTicks action_time);
155 
156   // Record any changes in a given histogram for transmission.
157   void RecordHistogramDelta(const std::string& histogram_name,
158                             const base::HistogramSamples& snapshot);
159 
160   // TODO(rkaplow): I think this can be a little refactored as it currently
161   // records a pretty arbitrary set of things.
162   // Records the current operating environment, including metrics provided by
163   // the specified |delegating_provider|. The current environment is
164   // returned as a SystemProfileProto.
165   const SystemProfileProto& RecordEnvironment(
166       DelegatingProvider* delegating_provider);
167 
168   // Loads the environment proto that was saved by the last RecordEnvironment()
169   // call from prefs. On success, returns true. Otherwise, (if there was no
170   // saved environment in prefs or it could not be decoded), returns false.
171   bool LoadSavedEnvironmentFromPrefs(PrefService* local_state);
172 
173   // Populates the log with data about the previous session.
174   // |delegating_provider| forwards the call to provide data to registered
175   // MetricsProviders. |local_state| is used to schedule a write because a side
176   // effect of providing some data is updating Local State prefs.
177   void RecordPreviousSessionData(DelegatingProvider* delegating_provider,
178                                  PrefService* local_state);
179 
180   // Populates the log with data about the current session. The uptimes are used
181   // to populate the log with info about how long Chrome has been running.
182   // |delegating_provider| forwards the call to provide data to registered
183   // MetricsProviders. |local_state| is used to schedule a write because a side
184   // effect of providing some data is updating Local State prefs.
185   void RecordCurrentSessionData(base::TimeDelta incremental_uptime,
186                                 base::TimeDelta uptime,
187                                 DelegatingProvider* delegating_provider,
188                                 PrefService* local_state);
189 
190   // Returns the current time using |network_clock_| if non-null (falls back to
191   // |clock_| otherwise). If |record_time_zone| is true, the returned time will
192   // also be populated with the time zone. Must be called on the main thread.
193   ChromeUserMetricsExtension::RealLocalTime GetCurrentClockTime(
194       bool record_time_zone);
195 
196   // Finalizes the log. Calling this function will make a call to CloseLog().
197   // |truncate_events| determines whether user action and omnibox data within
198   // the log should be trimmed/truncated (for bandwidth concerns).
199   // |current_app_version| is the current version of the application, and is
200   // used to determine whether the log data was obtained in a previous version.
201   // |close_time| is roughly the current time -- it is provided as a param
202   // since computing the current time can sometimes only be done on the main
203   // thread, and this method may be called on a background thread. The
204   // serialized proto of the finalized log will be written to |encoded_log|.
205   void FinalizeLog(
206       bool truncate_events,
207       const std::string& current_app_version,
208       std::optional<ChromeUserMetricsExtension::RealLocalTime> close_time,
209       std::string* encoded_log);
210 
211 #if BUILDFLAG(IS_CHROMEOS_ASH)
212   // Assigns a user ID to the log. This should be called immediately after
213   // consotruction if it should be applied.
214   void SetUserId(const std::string& user_id);
215 #endif
216 
log_type()217   LogType log_type() const { return log_type_; }
218 
log_metadata()219   const LogMetadata& log_metadata() const { return log_metadata_; }
220 
uma_proto()221   ChromeUserMetricsExtension* uma_proto() { return &uma_proto_; }
222 
uma_proto()223   const ChromeUserMetricsExtension* uma_proto() const { return &uma_proto_; }
224 
225  private:
226   // Stop writing to this record. None of the Record* methods can be called
227   // after this is called.
228   void CloseLog();
229 
230   // Records the log_written_by_app_version system_profile field if the
231   // |current_version| is different from the system_profile's app_version.
232   void RecordLogWrittenByAppVersionIfNeeded(const std::string& current_version);
233 
234   // Truncate some of the fields within the log that we want to restrict in
235   // size due to bandwidth concerns.
236   void TruncateEvents();
237 
238   // Write the default state of the enable metrics checkbox.
239   void WriteMetricsEnableDefault(EnableMetricsDefault metrics_default,
240                                  SystemProfileProto* system_profile);
241 
242   // Within the stability group, write attributes that need to be updated asap
243   // and can't be delayed until the user decides to restart chromium.
244   // Delaying these stats would bias metrics away from happy long lived
245   // chromium processes (ones that don't crash, and keep on running).
246   void WriteRealtimeStabilityAttributes(base::TimeDelta incremental_uptime,
247                                         base::TimeDelta uptime);
248 
249   // closed_ is true when record has been packed up for sending, and should
250   // no longer be written to.  It is only used for sanity checking.
251   bool closed_;
252 
253   // The type of the log, i.e. initial or ongoing.
254   const LogType log_type_;
255 
256   // Stores the protocol buffer representation for this log.
257   ChromeUserMetricsExtension uma_proto_;
258 
259   // Used to interact with the embedder. Weak pointer; must outlive |this|
260   // instance.
261   const raw_ptr<MetricsServiceClient> client_;
262 
263   // The time when the current log was created.
264   const base::TimeTicks creation_time_;
265 
266   // True if the environment has already been filled in by a call to
267   // RecordEnvironment() or LoadSavedEnvironmentFromPrefs().
268   bool has_environment_;
269 
270   // Optional metadata associated with the log.
271   LogMetadata log_metadata_;
272 
273   // The clock used to vend Time::Now().  Note that this is not used for the
274   // static function MetricsLog::GetCurrentTime(). Can be overridden for tests.
275   raw_ptr<base::Clock> clock_;
276 
277   // The NetworkTimeTracker used to provide higher-quality wall clock times than
278   // |clock_| (when available). Can be overridden for tests.
279   raw_ptr<const network_time::NetworkTimeTracker> network_clock_;
280 };
281 
282 }  // namespace metrics
283 
284 #endif  // COMPONENTS_METRICS_METRICS_LOG_H_
285