1 // Copyright 2018 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 #ifndef CHROME_BROWSER_METRICS_PERF_METRIC_COLLECTOR_H_
6 #define CHROME_BROWSER_METRICS_PERF_METRIC_COLLECTOR_H_
7 
8 #include <stdint.h>
9 
10 #include <memory>
11 #include <string>
12 
13 #include "base/macros.h"
14 #include "base/sequence_checker.h"
15 #include "base/time/time.h"
16 #include "base/timer/timer.h"
17 #include "chrome/browser/metrics/perf/collection_params.h"
18 
19 namespace metrics {
20 
21 class SampledProfile;
22 
23 namespace internal {
24 
25 // MetricCollector implements the basic collector functionality, including the
26 // scheduling and synchronization logic between the various trigger events, and
27 // the profile post-processing logic. Except for the constructor that can be
28 // invoked from a different thread, all its methods run on the same sequence,
29 // which is enforced by a sequence checker. A collector is managed by a
30 // MetricProvider, including the sequence on which it runs.
31 class MetricCollector {
32  public:
33   using ProfileDoneCallback =
34       base::RepeatingCallback<void(std::unique_ptr<SampledProfile>)>;
35 
36   // It may be invoked on a difference sequence than the member functions.
37   MetricCollector(const std::string& name,
38                   const CollectionParams& collection_params);
39 
40   virtual ~MetricCollector();
41 
42   virtual const char* ToolName() const = 0;
43 
44   void Init();
45 
46   // These methods are used to update the cached_data_size_ field via PostTask
47   // from the provider.
48   void AddCachedDataDelta(size_t delta);
49   void ResetCachedDataSize();
50 
51   // Turns on profile collection. Resets the timer that's used to schedule
52   // collections.
53   void RecordUserLogin(base::TimeTicks login_time);
54 
55   // Deactivates the timer and turns off profile collection. Does not delete any
56   // profile data that was already collected.
57   void StopTimer();
58 
59   // Schedules a collection after a resume from suspend event. A collection is
60   // scheduled with the probablity given by the sampling factor stored in
61   // |collection_params_|.
62   void ScheduleSuspendDoneCollection(base::TimeDelta sleep_duration);
63 
64   // Schedules a collection after a session restore event. A collection is
65   // scheduled with the probablity given by the sampling factor stored in
66   // |collection_params_|.
67   void ScheduleSessionRestoreCollection(int num_tabs_restored);
68 
69   // Called when a jank started/stopped.
70   void OnJankStarted();
71   void OnJankStopped();
72 
set_profile_done_callback(ProfileDoneCallback cb)73   void set_profile_done_callback(ProfileDoneCallback cb) {
74     profile_done_callback_ = std::move(cb);
75   }
76 
77  protected:
78   // Enumeration representing success and various failure modes for collecting
79   // profile data. These values are persisted to logs. Entries should not be
80   // renumbered and numeric values should never be reused.
81   enum class CollectionAttemptStatus {
82     SUCCESS,
83     NOT_READY_TO_COLLECT,
84     INCOGNITO_ACTIVE,
85     INCOGNITO_LAUNCHED,
86     PROTOBUF_NOT_PARSED,
87     ILLEGAL_DATA_RETURNED,
88     ALREADY_COLLECTING,
89     UNABLE_TO_COLLECT,
90     DATA_COLLECTION_FAILED,
91     SESSION_HAS_ZERO_SAMPLES,
92     NUM_OUTCOMES
93   };
94 
95   // Returns a WeakPtr to this instance.
96   virtual base::WeakPtr<MetricCollector> GetWeakPtr() = 0;
97 
98   // Collector specific initialization.
SetUp()99   virtual void SetUp() {}
100 
101   // Saves the given outcome to the uma histogram associated with the collector.
102   void AddToUmaHistogram(CollectionAttemptStatus outcome) const;
103 
104   // Returns whether the underlying timer is running or not.
IsRunning()105   bool IsRunning() { return timer_.IsRunning(); }
106   // Returns the current timer delay. Useful for debugging.
CurrentTimerDelay()107   base::TimeDelta CurrentTimerDelay() { return timer_.GetCurrentDelay(); }
108 
login_time()109   base::TimeTicks login_time() const { return login_time_; }
110 
111   // Collects perf data after a resume. |sleep_duration| is the duration the
112   // system was suspended before resuming. |time_after_resume_ms| is how long
113   // ago the system resumed.
114   void CollectPerfDataAfterResume(base::TimeDelta sleep_duration,
115                                   base::TimeDelta time_after_resume);
116 
117   // Collects perf data after a session restore. |time_after_restore| is how
118   // long ago the session restore started. |num_tabs_restored| is the total
119   // number of tabs being restored.
120   void CollectPerfDataAfterSessionRestore(base::TimeDelta time_after_restore,
121                                           int num_tabs_restored);
122 
123   // Selects a random time in the upcoming profiling interval that begins at
124   // |next_profiling_interval_start|. Schedules |timer| to invoke
125   // DoPeriodicCollection() when that time comes.
126   void ScheduleIntervalCollection();
127 
128   // Collects profiles on a repeating basis by calling CollectIfNecessary() and
129   // reschedules it to be collected again.
130   void DoPeriodicCollection();
131 
132   // Collects a profile for a given |trigger_event| if necessary.
133   void CollectIfNecessary(std::unique_ptr<SampledProfile> sampled_profile);
134 
135   // Returns if it's valid and safe for a collector to gather a profile.
136   // A collector implementation can override this logic.
137   virtual bool ShouldCollect() const;
138 
139   // Collector specific logic for collecting a profile.
140   virtual void CollectProfile(
141       std::unique_ptr<SampledProfile> sampled_profile) = 0;
142 
143   // Collector specific logic for stopping the current collection.
StopCollection()144   virtual void StopCollection() {}
145 
146   // Parses the given serialized perf data proto. If valid, it adds it to the
147   // given sampled_profile and stores it in the local profile data cache.
148   void SaveSerializedPerfProto(std::unique_ptr<SampledProfile> sampled_profile,
149                                std::string serialized_proto);
150 
151   // Returns a const reference to the collection_params.
collection_params()152   const CollectionParams& collection_params() const {
153     return collection_params_;
154   }
155 
156   // Returns a mutable reference to the collection_params, so that collectors
157   // and tests can update the params.
collection_params()158   CollectionParams& collection_params() { return collection_params_; }
159 
160   // The size of cached profile data.
161   size_t cached_data_size_ = 0;
162 
163   // Checks that some methods are called on the collector sequence.
164   SEQUENCE_CHECKER(sequence_checker_);
165 
166  private:
167   // Parameters controlling how profiles are collected. Initialized at
168   // collector creation time. Then accessed only on the collector sequence.
169   CollectionParams collection_params_;
170 
171   // For scheduling collection of profile data.
172   base::OneShotTimer timer_;
173 
174   // Record of the last login time.
175   base::TimeTicks login_time_;
176 
177   // Record of the start of the upcoming profiling interval.
178   base::TimeTicks next_profiling_interval_start_;
179 
180   // Tracks the last time a session restore was collected.
181   base::TimeTicks last_session_restore_collection_time_;
182 
183   // Name of the histogram that represents the success and various failure
184   // modes of collection attempts.
185   const std::string collect_uma_histogram_;
186 
187   // A callback to be Run on each successfully collected profile.
188   ProfileDoneCallback profile_done_callback_;
189 
190   DISALLOW_COPY_AND_ASSIGN(MetricCollector);
191 };
192 
193 }  // namespace internal
194 
195 }  // namespace metrics
196 
197 #endif  // CHROME_BROWSER_METRICS_PERF_METRIC_COLLECTOR_H_
198