1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 6 // the 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 #include <vector> 16 17 #include "base/callback_forward.h" 18 #include "base/macros.h" 19 #include "base/metrics/histogram_base.h" 20 #include "base/strings/string_piece_forward.h" 21 #include "base/time/time.h" 22 #include "components/metrics/metrics_reporting_default_state.h" 23 #include "third_party/metrics_proto/chrome_user_metrics_extension.pb.h" 24 #include "third_party/metrics_proto/system_profile.pb.h" 25 26 class PrefService; 27 28 namespace base { 29 class HistogramFlattener; 30 class HistogramSamples; 31 class HistogramSnapshotManager; 32 } // namespace base 33 34 namespace metrics { 35 36 class MetricsProvider; 37 class MetricsServiceClient; 38 class DelegatingProvider; 39 40 namespace internal { 41 // Maximum number of events before truncation. 42 constexpr int kOmniboxEventLimit = 5000; 43 constexpr int kUserActionEventLimit = 5000; 44 45 SystemProfileProto::InstallerPackage ToInstallerPackage( 46 base::StringPiece installer_package_name); 47 } // namespace internal 48 49 class MetricsLog { 50 public: 51 enum LogType { 52 INITIAL_STABILITY_LOG, // The initial log containing stability stats. 53 ONGOING_LOG, // Subsequent logs in a session. 54 INDEPENDENT_LOG, // An independent log from a previous session. 55 }; 56 57 // Loads "independent" metrics from a metrics provider and executes a 58 // callback when complete, which could be immediate or after some 59 // execution on a background thread. 60 class IndependentMetricsLoader { 61 public: 62 explicit IndependentMetricsLoader(std::unique_ptr<MetricsLog> log); 63 ~IndependentMetricsLoader(); 64 65 // Call ProvideIndependentMetrics (which may execute on a background thread) 66 // for the |metrics_provider| and execute the |done_callback| when complete 67 // with the result (true if successful). Though this can be called multiple 68 // times to include data from multiple providers, later calls will override 69 // system profile information set by earlier calls. 70 void Run(base::OnceCallback<void(bool)> done_callback, 71 MetricsProvider* metrics_provider); 72 73 // Extract the filled log. No more Run() operations can be done after this. 74 std::unique_ptr<MetricsLog> ReleaseLog(); 75 76 private: 77 std::unique_ptr<MetricsLog> log_; 78 std::unique_ptr<base::HistogramFlattener> flattener_; 79 std::unique_ptr<base::HistogramSnapshotManager> snapshot_manager_; 80 81 DISALLOW_COPY_AND_ASSIGN(IndependentMetricsLoader); 82 }; 83 84 // Creates a new metrics log of the specified type. 85 // |client_id| is the identifier for this profile on this installation 86 // |session_id| is an integer that's incremented on each application launch 87 // |client| is used to interact with the embedder. 88 // |local_state| is the PrefService that this instance should use. 89 // Note: |this| instance does not take ownership of the |client|, but rather 90 // stores a weak pointer to it. The caller should ensure that the |client| is 91 // valid for the lifetime of this class. 92 MetricsLog(const std::string& client_id, 93 int session_id, 94 LogType log_type, 95 MetricsServiceClient* client); 96 virtual ~MetricsLog(); 97 98 // Registers local state prefs used by this class. 99 static void RegisterPrefs(PrefRegistrySimple* registry); 100 101 // Computes the MD5 hash of the given string, and returns the first 8 bytes of 102 // the hash. 103 static uint64_t Hash(const std::string& value); 104 105 // Get the GMT buildtime for the current binary, expressed in seconds since 106 // January 1, 1970 GMT. 107 // The value is used to identify when a new build is run, so that previous 108 // reliability stats, from other builds, can be abandoned. 109 static int64_t GetBuildTime(); 110 111 // Convenience function to return the current time at a resolution in seconds. 112 // This wraps base::TimeTicks, and hence provides an abstract time that is 113 // always incrementing for use in measuring time durations. 114 static int64_t GetCurrentTime(); 115 116 // Record core profile settings into the SystemProfileProto. 117 static void RecordCoreSystemProfile(MetricsServiceClient* client, 118 SystemProfileProto* system_profile); 119 120 // Record core profile settings into the SystemProfileProto without a client. 121 static void RecordCoreSystemProfile( 122 const std::string& version, 123 metrics::SystemProfileProto::Channel channel, 124 const std::string& application_locale, 125 const std::string& package_name, 126 SystemProfileProto* system_profile); 127 128 // Records a user-initiated action. 129 void RecordUserAction(const std::string& key, base::TimeTicks action_time); 130 131 // Record any changes in a given histogram for transmission. 132 void RecordHistogramDelta(const std::string& histogram_name, 133 const base::HistogramSamples& snapshot); 134 135 // TODO(rkaplow): I think this can be a little refactored as it currently 136 // records a pretty arbitrary set of things. 137 // Records the current operating environment, including metrics provided by 138 // the specified |delegating_provider|. The current environment is 139 // returned as a SystemProfileProto. 140 const SystemProfileProto& RecordEnvironment( 141 DelegatingProvider* delegating_provider); 142 143 // Loads the environment proto that was saved by the last RecordEnvironment() 144 // call from prefs. On success, returns true and |app_version| contains the 145 // recovered version. Otherwise (if there was no saved environment in prefs 146 // or it could not be decoded), returns false and |app_version| is empty. 147 bool LoadSavedEnvironmentFromPrefs(PrefService* local_state, 148 std::string* app_version); 149 150 // Record data from providers about the previous session into the log. 151 void RecordPreviousSessionData(DelegatingProvider* delegating_provider); 152 153 // Record data from providers about the current session into the log. 154 void RecordCurrentSessionData(DelegatingProvider* delegating_provider, 155 base::TimeDelta incremental_uptime, 156 base::TimeDelta uptime); 157 158 // Stop writing to this record and generate the encoded representation. 159 // None of the Record* methods can be called after this is called. 160 void CloseLog(); 161 162 // Truncate some of the fields within the log that we want to restrict in 163 // size due to bandwidth concerns. 164 void TruncateEvents(); 165 166 // Fills |encoded_log| with the serialized protobuf representation of the 167 // record. Must only be called after CloseLog() has been called. 168 void GetEncodedLog(std::string* encoded_log); 169 creation_time()170 const base::TimeTicks& creation_time() const { return creation_time_; } 171 log_type()172 LogType log_type() const { return log_type_; } 173 174 // Returns the number of samples in this log, it is only valid after the 175 // histogram delta is calculated. samples_count()176 base::HistogramBase::Count samples_count() const { return samples_count_; } 177 178 // Exposed for the sake of mocking/accessing in test code. UmaProtoForTest()179 ChromeUserMetricsExtension* UmaProtoForTest() { return &uma_proto_; } 180 181 protected: 182 // Exposed for the sake of mocking/accessing in test code. 183 // TODO(1034679): migrate to public UmaProtoForTest() method. uma_proto()184 ChromeUserMetricsExtension* uma_proto() { return &uma_proto_; } 185 186 // Exposed to allow subclass to access to export the uma_proto. Can be used 187 // by external components to export logs to Chrome. uma_proto()188 const ChromeUserMetricsExtension* uma_proto() const { return &uma_proto_; } 189 190 private: 191 // Write the default state of the enable metrics checkbox. 192 void WriteMetricsEnableDefault(EnableMetricsDefault metrics_default, 193 SystemProfileProto* system_profile); 194 195 // Within the stability group, write attributes that need to be updated asap 196 // and can't be delayed until the user decides to restart chromium. 197 // Delaying these stats would bias metrics away from happy long lived 198 // chromium processes (ones that don't crash, and keep on running). 199 void WriteRealtimeStabilityAttributes(base::TimeDelta incremental_uptime, 200 base::TimeDelta uptime); 201 202 // closed_ is true when record has been packed up for sending, and should 203 // no longer be written to. It is only used for sanity checking. 204 bool closed_; 205 206 // The type of the log, i.e. initial or ongoing. 207 const LogType log_type_; 208 209 // Stores the protocol buffer representation for this log. 210 ChromeUserMetricsExtension uma_proto_; 211 212 // Used to interact with the embedder. Weak pointer; must outlive |this| 213 // instance. 214 MetricsServiceClient* const client_; 215 216 // The time when the current log was created. 217 const base::TimeTicks creation_time_; 218 219 // True if the environment has already been filled in by a call to 220 // RecordEnvironment() or LoadSavedEnvironmentFromPrefs(). 221 bool has_environment_; 222 223 // The number of samples in this log. 224 base::HistogramBase::Count samples_count_ = 0; 225 226 DISALLOW_COPY_AND_ASSIGN(MetricsLog); 227 }; 228 229 } // namespace metrics 230 231 #endif // COMPONENTS_METRICS_METRICS_LOG_H_ 232