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