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