• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 The Chromium Authors
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 COMPONENTS_METRICS_STRUCTURED_STRUCTURED_METRICS_SERVICE_H_
6 #define COMPONENTS_METRICS_STRUCTURED_STRUCTURED_METRICS_SERVICE_H_
7 
8 #include <memory>
9 
10 #include "base/functional/callback_forward.h"
11 #include "base/gtest_prod_util.h"
12 #include "base/memory/scoped_refptr.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/task/sequenced_task_runner.h"
15 #include "base/threading/sequence_bound.h"
16 #include "components/metrics/structured/reporting/structured_metrics_reporting_service.h"
17 #include "components/metrics/structured/storage_manager.h"
18 #include "components/metrics/structured/structured_metrics_recorder.h"
19 #include "components/metrics/structured/structured_metrics_scheduler.h"
20 #include "components/metrics/unsent_log_store.h"
21 #include "third_party/metrics_proto/chrome_user_metrics_extension.pb.h"
22 
23 FORWARD_DECLARE_TEST(StructuredMetricsServiceTest, RotateLogs);
24 
25 class PrefRegistrySimple;
26 
27 namespace metrics {
28 class StructuredMetricsServiceTestBase;
29 class TestStructuredMetricsServiceDisabled;
30 class TestStructuredMetricsService;
31 
32 FORWARD_DECLARE_TEST(TestStructuredMetricsServiceDisabled,
33                      ValidStateWhenDisabled);
34 
35 FORWARD_DECLARE_TEST(TestStructuredMetricsService, CreateLogs);
36 }  // namespace metrics
37 
38 namespace metrics::structured {
39 
40 class OobeStructuredMetricsWatcher;
41 class StructuredMetricsServiceTest;
42 class StructuredMetricsMixin;
43 
44 FORWARD_DECLARE_TEST(StructuredMetricsServiceTest, RotateLogs);
45 
46 // The Structured Metrics Service is responsible for collecting and uploading
47 // Structured Metric events.
48 class StructuredMetricsService final : public StorageManager::StorageDelegate {
49  public:
50   StructuredMetricsService(MetricsServiceClient* client,
51                            PrefService* local_state,
52                            scoped_refptr<StructuredMetricsRecorder> recorder);
53 
54   ~StructuredMetricsService() override;
55 
56   StructuredMetricsService(const StructuredMetricsService&) = delete;
57   StructuredMetricsService& operator=(StructuredMetricsService&) = delete;
58 
59   void EnableRecording();
60   void DisableRecording();
61 
62   void EnableReporting();
63   void DisableReporting();
64 
65   // Flushes any event currently in the recorder to prefs.
66   void Flush(metrics::MetricsLogsEventManager::CreateReason reason);
67 
68   // Clears all event and log data.
69   void Purge();
70 
71   MetricsServiceClient* GetMetricsServiceClient() const;
72 
reporting_active()73   bool reporting_active() const {
74     return reporting_service_->reporting_active();
75   }
76 
recording_enabled()77   bool recording_enabled() const { return recorder_->recording_enabled(); }
78 
recorder()79   StructuredMetricsRecorder* recorder() { return recorder_.get(); }
80 
81   static void RegisterPrefs(PrefRegistrySimple* registry);
82 
log_store()83   metrics::LogStore* log_store() { return reporting_service_->log_store(); }
84 
85  private:
86   friend class StructuredMetricsServiceTest;
87   friend class StructuredMetricsMixin;
88 #if BUILDFLAG(IS_CHROMEOS)
89   friend class OobeStructuredMetricsWatcher;
90 #endif
91   friend class metrics::StructuredMetricsServiceTestBase;
92 
93   FRIEND_TEST_ALL_PREFIXES(metrics::structured::StructuredMetricsServiceTest,
94                            RotateLogs);
95   FRIEND_TEST_ALL_PREFIXES(metrics::TestStructuredMetricsService, CreateLogs);
96   FRIEND_TEST_ALL_PREFIXES(metrics::TestStructuredMetricsServiceDisabled,
97                            ValidStateWhenDisabled);
98 
99   // Sets the instance of the recorder used for test.
100   void SetRecorderForTest(scoped_refptr<StructuredMetricsRecorder> recorder);
101 
102   // Callback function to get the upload interval.
103   base::TimeDelta GetUploadTimeInterval();
104 
105   // Creates a new log and sends any currently stages logs.
106   void RotateLogsAndSend();
107 
108   // Collects the events from the recorder and builds a new log on a separate
109   // task.
110   //
111   // An upload is triggered once the task is completed.
112   void BuildAndStoreLog(metrics::MetricsLogsEventManager::CreateReason reason,
113                         bool notify_scheduler);
114 
115   // Collects the events from the recorder and builds a new log on the current
116   // thread.
117   //
118   // An upload is triggered after the log has been stored.
119   // Used on Windows, Mac, and Linux and during shutdown.
120   void BuildAndStoreLogSync(
121       metrics::MetricsLogsEventManager::CreateReason reason,
122       bool notify_scheduler);
123 
124   // Populates an UMA proto with data that must be accessed form the UI
125   // sequence. A task to collect events is posted which updates the created UMA
126   // proto. On Windows, Mac, and Linux logs are built synchronously.
127   //
128   // Must be called from the UI sequence.
129   void CreateLogs(metrics::MetricsLogsEventManager::CreateReason reason,
130                   bool notify_scheduler);
131 
132   // Adds metadata to the uma proto, stores a temporary log into the log store,
133   // and starts an upload.
134   void StoreLogAndStartUpload(
135       metrics::MetricsLogsEventManager::CreateReason reason,
136       bool notify_scheduler,
137       ChromeUserMetricsExtension uma_proto);
138 
139   // Starts the initialization process for |this|.
140   void Initialize();
141 
142   // Fills out the UMA proto to be sent.
143   void InitializeUmaProto(ChromeUserMetricsExtension& uma_proto);
144 
145   // Triggers an upload of recorded events outside of the normal cadence.
146   // This doesn't interfere with the normal cadence.
147   void ManualUpload();
148 
149   // Queue an upload if there are logs stored in the log store. This is meant to
150   // be used to start an upload when the service starts, so we do not have to
151   // wait until first upload to send events from the previous session.
152   //
153   // Reporting is assumed to be enabled by function. Must be checked before
154   // called.
155   void MaybeStartUpload();
156 
157   // Sets callback to be performed after a logs is created and stored. When set
158   // uploads will be blocked.
159   void SetCreateLogsCallbackInTests(base::OnceClosure callback);
160 
161   // StorageManager::StorageDelegate:
162   void OnFlushed(const FlushedKey& key) override;
163   void OnDeleted(const FlushedKey& key, DeleteReason reason) override;
164 
165   // Helper function to serialize a ChromeUserMetricsExtension proto.
166   static std::string SerializeLog(const ChromeUserMetricsExtension& uma_proto);
167 
168   // Retrieves the storage parameters to control the reporting service.
169   static UnsentLogStore::UnsentLogStoreLimits GetLogStoreLimits();
170 
171   // Manages on-device recording of events.
172   scoped_refptr<StructuredMetricsRecorder> recorder_;
173 
174   // Service for uploading completed logs.
175   std::unique_ptr<reporting::StructuredMetricsReportingService>
176       reporting_service_;
177 
178   // Schedules when logs will be created.
179   std::unique_ptr<StructuredMetricsScheduler> scheduler_;
180 
181   // Marks that initialization has completed.
182   bool initialize_complete_ = false;
183 
184   // Represents if structured metrics and the service is enabled. This isn't
185   // to indicate if the service is recording.
186   bool structured_metrics_enabled_ = false;
187 
188   // Flag to make sure MaybeStartUpload() isn't called twice.
189   bool initial_upload_started_ = false;
190 
191   // The metrics client |this| is service is associated.
192   raw_ptr<MetricsServiceClient> client_;
193 
194   // Callback to be performed once a log is created and stored.
195   base::OnceClosure create_log_callback_for_tests_;
196 
197   SEQUENCE_CHECKER(sequence_checker_);
198 
199 // Access to |recorder_| through |task_runner_| is only needed on Ash Chrome.
200 // Other platforms can continue to access |recorder_| directly.
201 #if BUILDFLAG(IS_CHROMEOS_ASH)
202   // An IO task runner for creating logs.
203   scoped_refptr<base::SequencedTaskRunner> task_runner_;
204 
205   // A helper class for performing asynchronous IO task on the
206   // StructuredMetricsRecorder.
207   class ServiceIOHelper {
208    public:
209     explicit ServiceIOHelper(scoped_refptr<StructuredMetricsRecorder> recorder);
210 
211     ~ServiceIOHelper();
212 
213     // Reads the events from |recorder_|.
214     ChromeUserMetricsExtension ProvideEvents();
215 
216    private:
217     // Access to the recorder is thead-safe.
218     scoped_refptr<StructuredMetricsRecorder> recorder_;
219   };
220 
221   // Holds a refptr to |recorder_| and provides access through |task_runner_|.
222   base::SequenceBound<ServiceIOHelper> io_helper_;
223 #endif
224   base::WeakPtrFactory<StructuredMetricsService> weak_factory_{this};
225 };
226 
227 }  // namespace metrics::structured
228 
229 #endif  // COMPONENTS_METRICS_STRUCTURED_STRUCTURED_METRICS_SERVICE_H_
230