File: metrics_log.h

package info (click to toggle)
chromium 120.0.6099.224-1~deb11u1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 6,112,112 kB
  • sloc: cpp: 32,907,025; ansic: 8,148,123; javascript: 3,679,536; python: 2,031,248; asm: 959,718; java: 804,675; xml: 617,256; sh: 111,417; objc: 100,835; perl: 88,443; cs: 53,032; makefile: 29,579; fortran: 24,137; php: 21,162; tcl: 21,147; sql: 20,809; ruby: 17,735; pascal: 12,864; yacc: 8,045; lisp: 3,388; lex: 1,323; ada: 727; awk: 329; jsp: 267; csh: 117; exp: 43; sed: 37
file content (269 lines) | stat: -rw-r--r-- 11,182 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file defines a set of user experience metrics data recorded by the
// MetricsService. This is the unit of data that is sent to the server.

#ifndef COMPONENTS_METRICS_METRICS_LOG_H_
#define COMPONENTS_METRICS_METRICS_LOG_H_

#include <stdint.h>

#include <memory>
#include <string>

#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_base.h"
#include "base/strings/string_piece_forward.h"
#include "base/time/time.h"
#include "build/chromeos_buildflags.h"
#include "components/metrics/metrics_reporting_default_state.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/metrics_proto/chrome_user_metrics_extension.pb.h"
#include "third_party/metrics_proto/system_profile.pb.h"

class PrefService;

namespace base {
class Clock;
class HistogramSamples;
}  // namespace base

namespace network_time {
class NetworkTimeTracker;
}  // namespace network_time

namespace metrics {

// Holds optional metadata associated with a log to be stored.
struct LogMetadata {
  LogMetadata();
  LogMetadata(absl::optional<base::HistogramBase::Count> samples_count,
              absl::optional<uint64_t> user_id);
  LogMetadata(const LogMetadata& other);
  ~LogMetadata();

  // Adds |sample_count| to |samples_count|. If |samples_count| is empty, then
  // |sample_count| will populate |samples_count|.
  void AddSampleCount(base::HistogramBase::Count sample_count);

  // The total number of samples in this log if applicable.
  absl::optional<base::HistogramBase::Count> samples_count;

  // User id associated with the log.
  absl::optional<uint64_t> user_id;
};

class MetricsServiceClient;
class DelegatingProvider;

namespace internal {
// Maximum number of events before truncation.
constexpr int kOmniboxEventLimit = 5000;
constexpr int kUserActionEventLimit = 5000;

SystemProfileProto::InstallerPackage ToInstallerPackage(
    base::StringPiece installer_package_name);
}  // namespace internal

class MetricsLog {
 public:
  enum LogType {
    INITIAL_STABILITY_LOG,  // The initial log containing stability stats.
    ONGOING_LOG,            // Subsequent logs in a session.
    INDEPENDENT_LOG,        // An independent log from a previous session.
  };

  // Creates a new metrics log of the specified type.
  // |client_id| is the identifier for this profile on this installation
  // |session_id| is an integer that's incremented on each application launch
  // |client| is used to interact with the embedder.
  // Note: |this| instance does not take ownership of the |client|, but rather
  // stores a weak pointer to it. The caller should ensure that the |client| is
  // valid for the lifetime of this class.
  MetricsLog(const std::string& client_id,
             int session_id,
             LogType log_type,
             MetricsServiceClient* client);
  // As above, with a |clock| and |network_clock| to use to vend Now() calls. As
  // with |client|, the caller must ensure both remain valid for the lifetime of
  // this class.
  MetricsLog(const std::string& client_id,
             int session_id,
             LogType log_type,
             base::Clock* clock,
             const network_time::NetworkTimeTracker* network_clock,
             MetricsServiceClient* client);

  MetricsLog(const MetricsLog&) = delete;
  MetricsLog& operator=(const MetricsLog&) = delete;
  virtual ~MetricsLog();

  // Registers local state prefs used by this class.
  static void RegisterPrefs(PrefRegistrySimple* registry);

  // Computes the MD5 hash of the given string, and returns the first 8 bytes of
  // the hash.
  static uint64_t Hash(const std::string& value);

  // Get the GMT buildtime for the current binary, expressed in seconds since
  // January 1, 1970 GMT.
  // The value is used to identify when a new build is run, so that previous
  // reliability stats, from other builds, can be abandoned.
  static int64_t GetBuildTime();

  // Convenience function to return the current time at a resolution in seconds.
  // This wraps base::TimeTicks, and hence provides an abstract time that is
  // always incrementing for use in measuring time durations.
  static int64_t GetCurrentTime();

  // Records core profile settings into the SystemProfileProto.
  static void RecordCoreSystemProfile(MetricsServiceClient* client,
                                      SystemProfileProto* system_profile);

  // Records core profile settings into the SystemProfileProto without a client.
  static void RecordCoreSystemProfile(
      const std::string& version,
      metrics::SystemProfileProto::Channel channel,
      bool is_extended_stable_channel,
      const std::string& application_locale,
      const std::string& package_name,
      SystemProfileProto* system_profile);

  // Assign a unique record id to this log.
  void AssignRecordId(PrefService* local_state);

  // Records a user-initiated action.
  void RecordUserAction(const std::string& key, base::TimeTicks action_time);

  // Record any changes in a given histogram for transmission.
  void RecordHistogramDelta(const std::string& histogram_name,
                            const base::HistogramSamples& snapshot);

  // TODO(rkaplow): I think this can be a little refactored as it currently
  // records a pretty arbitrary set of things.
  // Records the current operating environment, including metrics provided by
  // the specified |delegating_provider|. The current environment is
  // returned as a SystemProfileProto.
  const SystemProfileProto& RecordEnvironment(
      DelegatingProvider* delegating_provider);

  // Loads the environment proto that was saved by the last RecordEnvironment()
  // call from prefs. On success, returns true. Otherwise, (if there was no
  // saved environment in prefs or it could not be decoded), returns false.
  bool LoadSavedEnvironmentFromPrefs(PrefService* local_state);

  // Populates the log with data about the previous session.
  // |delegating_provider| forwards the call to provide data to registered
  // MetricsProviders. |local_state| is used to schedule a write because a side
  // effect of providing some data is updating Local State prefs.
  void RecordPreviousSessionData(DelegatingProvider* delegating_provider,
                                 PrefService* local_state);

  // Populates the log with data about the current session. The uptimes are used
  // to populate the log with info about how long Chrome has been running.
  // |delegating_provider| forwards the call to provide data to registered
  // MetricsProviders. |local_state| is used to schedule a write because a side
  // effect of providing some data is updating Local State prefs.
  void RecordCurrentSessionData(base::TimeDelta incremental_uptime,
                                base::TimeDelta uptime,
                                DelegatingProvider* delegating_provider,
                                PrefService* local_state);

  // Returns the current time using |network_clock_| if non-null (falls back to
  // |clock_| otherwise). If |record_time_zone| is true, the returned time will
  // also be populated with the time zone. Must be called on the main thread.
  ChromeUserMetricsExtension::RealLocalTime GetCurrentClockTime(
      bool record_time_zone);

  // Finalizes the log. Calling this function will make a call to CloseLog().
  // |truncate_events| determines whether user action and omnibox data within
  // the log should be trimmed/truncated (for bandwidth concerns).
  // |current_app_version| is the current version of the application, and is
  // used to determine whether the log data was obtained in a previous version.
  // |close_time| is roughly the current time -- it is provided as a param
  // since computing the current time can sometimes only be done on the main
  // thread, and this method may be called on a background thread. The
  // serialized proto of the finalized log will be written to |encoded_log|.
  void FinalizeLog(
      bool truncate_events,
      const std::string& current_app_version,
      absl::optional<ChromeUserMetricsExtension::RealLocalTime> close_time,
      std::string* encoded_log);

#if BUILDFLAG(IS_CHROMEOS_ASH)
  // Assigns a user ID to the log. This should be called immediately after
  // consotruction if it should be applied.
  void SetUserId(const std::string& user_id);
#endif

  LogType log_type() const { return log_type_; }

  const LogMetadata& log_metadata() const { return log_metadata_; }

  ChromeUserMetricsExtension* uma_proto() { return &uma_proto_; }

  const ChromeUserMetricsExtension* uma_proto() const { return &uma_proto_; }

 private:
  // Stop writing to this record. None of the Record* methods can be called
  // after this is called.
  void CloseLog();

  // Records the log_written_by_app_version system_profile field if the
  // |current_version| is different from the system_profile's app_version.
  void RecordLogWrittenByAppVersionIfNeeded(const std::string& current_version);

  // Truncate some of the fields within the log that we want to restrict in
  // size due to bandwidth concerns.
  void TruncateEvents();

  // Write the default state of the enable metrics checkbox.
  void WriteMetricsEnableDefault(EnableMetricsDefault metrics_default,
                                 SystemProfileProto* system_profile);

  // Within the stability group, write attributes that need to be updated asap
  // and can't be delayed until the user decides to restart chromium.
  // Delaying these stats would bias metrics away from happy long lived
  // chromium processes (ones that don't crash, and keep on running).
  void WriteRealtimeStabilityAttributes(base::TimeDelta incremental_uptime,
                                        base::TimeDelta uptime);

  // closed_ is true when record has been packed up for sending, and should
  // no longer be written to.  It is only used for sanity checking.
  bool closed_;

  // The type of the log, i.e. initial or ongoing.
  const LogType log_type_;

  // Stores the protocol buffer representation for this log.
  ChromeUserMetricsExtension uma_proto_;

  // Used to interact with the embedder. Weak pointer; must outlive |this|
  // instance.
  const raw_ptr<MetricsServiceClient> client_;

  // The time when the current log was created.
  const base::TimeTicks creation_time_;

  // True if the environment has already been filled in by a call to
  // RecordEnvironment() or LoadSavedEnvironmentFromPrefs().
  bool has_environment_;

  // Optional metadata associated with the log.
  LogMetadata log_metadata_;

  // The clock used to vend Time::Now().  Note that this is not used for the
  // static function MetricsLog::GetCurrentTime(). Can be overridden for tests.
  raw_ptr<base::Clock> clock_;

  // The NetworkTimeTracker used to provide higher-quality wall clock times than
  // |clock_| (when available). Can be overridden for tests.
  raw_ptr<const network_time::NetworkTimeTracker> network_clock_;
};

}  // namespace metrics

#endif  // COMPONENTS_METRICS_METRICS_LOG_H_