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_
|