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