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