• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // 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 <string>
15 
16 #include "base/functional/callback_forward.h"
17 #include "base/memory/raw_ptr.h"
18 #include "base/metrics/histogram_base.h"
19 #include "base/strings/string_piece.h"
20 #include "base/time/time.h"
21 #include "build/chromeos_buildflags.h"
22 #include "components/metrics/metrics_reporting_default_state.h"
23 #include "third_party/abseil-cpp/absl/types/optional.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(absl::optional<base::HistogramBase::Count> samples_count,
52               absl::optional<uint64_t> user_id,
53               absl::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   absl::optional<base::HistogramBase::Count> samples_count;
63 
64   // User id associated with the log.
65   absl::optional<uint64_t> user_id;
66 
67   // For UKM logs, indicates the type of data.
68   absl::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 record id to this log.
148   void AssignRecordId(PrefService* local_state);
149 
150   // Records a user-initiated action.
151   void RecordUserAction(const std::string& key, base::TimeTicks action_time);
152 
153   // Record any changes in a given histogram for transmission.
154   void RecordHistogramDelta(const std::string& histogram_name,
155                             const base::HistogramSamples& snapshot);
156 
157   // TODO(rkaplow): I think this can be a little refactored as it currently
158   // records a pretty arbitrary set of things.
159   // Records the current operating environment, including metrics provided by
160   // the specified |delegating_provider|. The current environment is
161   // returned as a SystemProfileProto.
162   const SystemProfileProto& RecordEnvironment(
163       DelegatingProvider* delegating_provider);
164 
165   // Loads the environment proto that was saved by the last RecordEnvironment()
166   // call from prefs. On success, returns true. Otherwise, (if there was no
167   // saved environment in prefs or it could not be decoded), returns false.
168   bool LoadSavedEnvironmentFromPrefs(PrefService* local_state);
169 
170   // Populates the log with data about the previous session.
171   // |delegating_provider| forwards the call to provide data to registered
172   // MetricsProviders. |local_state| is used to schedule a write because a side
173   // effect of providing some data is updating Local State prefs.
174   void RecordPreviousSessionData(DelegatingProvider* delegating_provider,
175                                  PrefService* local_state);
176 
177   // Populates the log with data about the current session. The uptimes are used
178   // to populate the log with info about how long Chrome has been running.
179   // |delegating_provider| forwards the call to provide data to registered
180   // MetricsProviders. |local_state| is used to schedule a write because a side
181   // effect of providing some data is updating Local State prefs.
182   void RecordCurrentSessionData(base::TimeDelta incremental_uptime,
183                                 base::TimeDelta uptime,
184                                 DelegatingProvider* delegating_provider,
185                                 PrefService* local_state);
186 
187   // Returns the current time using |network_clock_| if non-null (falls back to
188   // |clock_| otherwise). If |record_time_zone| is true, the returned time will
189   // also be populated with the time zone. Must be called on the main thread.
190   ChromeUserMetricsExtension::RealLocalTime GetCurrentClockTime(
191       bool record_time_zone);
192 
193   // Finalizes the log. Calling this function will make a call to CloseLog().
194   // |truncate_events| determines whether user action and omnibox data within
195   // the log should be trimmed/truncated (for bandwidth concerns).
196   // |current_app_version| is the current version of the application, and is
197   // used to determine whether the log data was obtained in a previous version.
198   // |close_time| is roughly the current time -- it is provided as a param
199   // since computing the current time can sometimes only be done on the main
200   // thread, and this method may be called on a background thread. The
201   // serialized proto of the finalized log will be written to |encoded_log|.
202   void FinalizeLog(
203       bool truncate_events,
204       const std::string& current_app_version,
205       absl::optional<ChromeUserMetricsExtension::RealLocalTime> close_time,
206       std::string* encoded_log);
207 
208 #if BUILDFLAG(IS_CHROMEOS_ASH)
209   // Assigns a user ID to the log. This should be called immediately after
210   // consotruction if it should be applied.
211   void SetUserId(const std::string& user_id);
212 #endif
213 
log_type()214   LogType log_type() const { return log_type_; }
215 
log_metadata()216   const LogMetadata& log_metadata() const { return log_metadata_; }
217 
uma_proto()218   ChromeUserMetricsExtension* uma_proto() { return &uma_proto_; }
219 
uma_proto()220   const ChromeUserMetricsExtension* uma_proto() const { return &uma_proto_; }
221 
222  private:
223   // Stop writing to this record. None of the Record* methods can be called
224   // after this is called.
225   void CloseLog();
226 
227   // Records the log_written_by_app_version system_profile field if the
228   // |current_version| is different from the system_profile's app_version.
229   void RecordLogWrittenByAppVersionIfNeeded(const std::string& current_version);
230 
231   // Truncate some of the fields within the log that we want to restrict in
232   // size due to bandwidth concerns.
233   void TruncateEvents();
234 
235   // Write the default state of the enable metrics checkbox.
236   void WriteMetricsEnableDefault(EnableMetricsDefault metrics_default,
237                                  SystemProfileProto* system_profile);
238 
239   // Within the stability group, write attributes that need to be updated asap
240   // and can't be delayed until the user decides to restart chromium.
241   // Delaying these stats would bias metrics away from happy long lived
242   // chromium processes (ones that don't crash, and keep on running).
243   void WriteRealtimeStabilityAttributes(base::TimeDelta incremental_uptime,
244                                         base::TimeDelta uptime);
245 
246   // closed_ is true when record has been packed up for sending, and should
247   // no longer be written to.  It is only used for sanity checking.
248   bool closed_;
249 
250   // The type of the log, i.e. initial or ongoing.
251   const LogType log_type_;
252 
253   // Stores the protocol buffer representation for this log.
254   ChromeUserMetricsExtension uma_proto_;
255 
256   // Used to interact with the embedder. Weak pointer; must outlive |this|
257   // instance.
258   const raw_ptr<MetricsServiceClient> client_;
259 
260   // The time when the current log was created.
261   const base::TimeTicks creation_time_;
262 
263   // True if the environment has already been filled in by a call to
264   // RecordEnvironment() or LoadSavedEnvironmentFromPrefs().
265   bool has_environment_;
266 
267   // Optional metadata associated with the log.
268   LogMetadata log_metadata_;
269 
270   // The clock used to vend Time::Now().  Note that this is not used for the
271   // static function MetricsLog::GetCurrentTime(). Can be overridden for tests.
272   raw_ptr<base::Clock> clock_;
273 
274   // The NetworkTimeTracker used to provide higher-quality wall clock times than
275   // |clock_| (when available). Can be overridden for tests.
276   raw_ptr<const network_time::NetworkTimeTracker> network_clock_;
277 };
278 
279 }  // namespace metrics
280 
281 #endif  // COMPONENTS_METRICS_METRICS_LOG_H_
282