1 // Copyright 2017 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 #include "components/metrics/metrics_log_store.h"
6
7 #include <string_view>
8
9 #include "components/metrics/metrics_pref_names.h"
10 #include "components/metrics/metrics_service_client.h"
11 #include "components/metrics/unsent_log_store_metrics_impl.h"
12 #include "components/prefs/pref_registry_simple.h"
13
14 namespace metrics {
15
16 // static
RegisterPrefs(PrefRegistrySimple * registry)17 void MetricsLogStore::RegisterPrefs(PrefRegistrySimple* registry) {
18 registry->RegisterListPref(prefs::kMetricsInitialLogs);
19 registry->RegisterListPref(prefs::kMetricsOngoingLogs);
20 registry->RegisterDictionaryPref(prefs::kMetricsInitialLogsMetadata);
21 registry->RegisterDictionaryPref(prefs::kMetricsOngoingLogsMetadata);
22 }
23
MetricsLogStore(PrefService * local_state,StorageLimits storage_limits,const std::string & signing_key,MetricsLogsEventManager * logs_event_manager)24 MetricsLogStore::MetricsLogStore(PrefService* local_state,
25 StorageLimits storage_limits,
26 const std::string& signing_key,
27 MetricsLogsEventManager* logs_event_manager)
28 : unsent_logs_loaded_(false),
29 logs_event_manager_(logs_event_manager),
30 initial_log_queue_(
31 std::make_unique<UnsentLogStoreMetricsImpl>(),
32 local_state,
33 prefs::kMetricsInitialLogs,
34 prefs::kMetricsInitialLogsMetadata,
35 UnsentLogStore::UnsentLogStoreLimits{
36 storage_limits.initial_log_queue_limits.min_log_count,
37 storage_limits.initial_log_queue_limits.min_queue_size_bytes,
38 // Each individual initial log can be any size.
39 /*max_log_size_bytes=*/0},
40 signing_key,
41 logs_event_manager),
42 ongoing_log_queue_(std::make_unique<UnsentLogStoreMetricsImpl>(),
43 local_state,
44 prefs::kMetricsOngoingLogs,
45 prefs::kMetricsOngoingLogsMetadata,
46 storage_limits.ongoing_log_queue_limits,
47 signing_key,
48 logs_event_manager) {}
49
50 MetricsLogStore::~MetricsLogStore() = default;
51
LoadPersistedUnsentLogs()52 void MetricsLogStore::LoadPersistedUnsentLogs() {
53 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
54
55 {
56 MetricsLogsEventManager::ScopedNotifyLogType scoped_log_type(
57 logs_event_manager_, MetricsLog::LogType::INITIAL_STABILITY_LOG);
58 initial_log_queue_.LoadPersistedUnsentLogs();
59 }
60
61 {
62 // Note that we assume that logs loaded from the persistent storage for
63 // |ongoing_log_queue_| are of type "ongoing". They could, however, be
64 // independent logs, but we unfortunately cannot determine this since we
65 // don't persist the type of log.
66 MetricsLogsEventManager::ScopedNotifyLogType scoped_log_type(
67 logs_event_manager_, MetricsLog::LogType::ONGOING_LOG);
68 ongoing_log_queue_.LoadPersistedUnsentLogs();
69 }
70
71 unsent_logs_loaded_ = true;
72 }
73
StoreLog(const std::string & log_data,MetricsLog::LogType log_type,const LogMetadata & log_metadata,MetricsLogsEventManager::CreateReason reason)74 void MetricsLogStore::StoreLog(const std::string& log_data,
75 MetricsLog::LogType log_type,
76 const LogMetadata& log_metadata,
77 MetricsLogsEventManager::CreateReason reason) {
78 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
79
80 MetricsLogsEventManager::ScopedNotifyLogType scoped_log_type(
81 logs_event_manager_, log_type);
82 GetLogStoreForLogType(log_type)->StoreLog(log_data, log_metadata, reason);
83 }
84
StoreLogInfo(std::unique_ptr<UnsentLogStore::LogInfo> log_info,size_t uncompressed_log_size,MetricsLog::LogType log_type,MetricsLogsEventManager::CreateReason reason)85 void MetricsLogStore::StoreLogInfo(
86 std::unique_ptr<UnsentLogStore::LogInfo> log_info,
87 size_t uncompressed_log_size,
88 MetricsLog::LogType log_type,
89 MetricsLogsEventManager::CreateReason reason) {
90 MetricsLogsEventManager::ScopedNotifyLogType scoped_log_type(
91 logs_event_manager_, log_type);
92 GetLogStoreForLogType(log_type)->StoreLogInfo(std::move(log_info),
93 uncompressed_log_size, reason);
94 }
95
Purge()96 void MetricsLogStore::Purge() {
97 initial_log_queue_.Purge();
98 ongoing_log_queue_.Purge();
99 if (has_alternate_ongoing_log_store()) {
100 alternate_ongoing_log_queue_->Purge();
101 }
102 }
103
GetSigningKeyForLogType(MetricsLog::LogType log_type)104 const std::string& MetricsLogStore::GetSigningKeyForLogType(
105 MetricsLog::LogType log_type) {
106 return GetLogStoreForLogType(log_type)->signing_key();
107 }
108
SetAlternateOngoingLogStore(std::unique_ptr<UnsentLogStore> log_store)109 void MetricsLogStore::SetAlternateOngoingLogStore(
110 std::unique_ptr<UnsentLogStore> log_store) {
111 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
112
113 DCHECK(!has_alternate_ongoing_log_store());
114 DCHECK(unsent_logs_loaded_);
115 alternate_ongoing_log_queue_ = std::move(log_store);
116 alternate_ongoing_log_queue_->SetLogsEventManager(logs_event_manager_);
117
118 // Note that we assume that logs loaded from the persistent storage for
119 // |alternate_ongoing_log_queue_| are of type "ongoing". They could, however,
120 // be independent logs, but we unfortunately cannot determine this since we
121 // don't persist the type of log.
122 MetricsLogsEventManager::ScopedNotifyLogType scoped_log_type(
123 logs_event_manager_, MetricsLog::LogType::ONGOING_LOG);
124 alternate_ongoing_log_queue_->LoadPersistedUnsentLogs();
125 }
126
UnsetAlternateOngoingLogStore()127 void MetricsLogStore::UnsetAlternateOngoingLogStore() {
128 DCHECK(has_alternate_ongoing_log_store());
129 alternate_ongoing_log_queue_->TrimAndPersistUnsentLogs(
130 /*overwrite_in_memory_store=*/true);
131 alternate_ongoing_log_queue_.reset();
132 }
133
has_unsent_logs() const134 bool MetricsLogStore::has_unsent_logs() const {
135 return initial_log_queue_.has_unsent_logs() ||
136 ongoing_log_queue_.has_unsent_logs() ||
137 alternate_ongoing_log_store_has_unsent_logs();
138 }
139
has_staged_log() const140 bool MetricsLogStore::has_staged_log() const {
141 return initial_log_queue_.has_staged_log() ||
142 ongoing_log_queue_.has_staged_log() ||
143 alternate_ongoing_log_store_has_staged_log();
144 }
145
staged_log() const146 const std::string& MetricsLogStore::staged_log() const {
147 return get_staged_log_queue()->staged_log();
148 }
149
staged_log_hash() const150 const std::string& MetricsLogStore::staged_log_hash() const {
151 return get_staged_log_queue()->staged_log_hash();
152 }
153
staged_log_signature() const154 const std::string& MetricsLogStore::staged_log_signature() const {
155 return get_staged_log_queue()->staged_log_signature();
156 }
157
staged_log_user_id() const158 std::optional<uint64_t> MetricsLogStore::staged_log_user_id() const {
159 return get_staged_log_queue()->staged_log_user_id();
160 }
161
staged_log_metadata() const162 const LogMetadata MetricsLogStore::staged_log_metadata() const {
163 return get_staged_log_queue()->staged_log_metadata();
164 }
165
has_alternate_ongoing_log_store() const166 bool MetricsLogStore::has_alternate_ongoing_log_store() const {
167 return alternate_ongoing_log_queue_ != nullptr;
168 }
169
get_staged_log_queue() const170 const UnsentLogStore* MetricsLogStore::get_staged_log_queue() const {
171 DCHECK(has_staged_log());
172
173 // This is the order in which logs should be staged. Should be consistent with
174 // StageNextLog.
175 if (initial_log_queue_.has_staged_log())
176 return &initial_log_queue_;
177 else if (alternate_ongoing_log_store_has_staged_log())
178 return alternate_ongoing_log_queue_.get();
179 return &ongoing_log_queue_;
180 }
181
alternate_ongoing_log_store_has_unsent_logs() const182 bool MetricsLogStore::alternate_ongoing_log_store_has_unsent_logs() const {
183 return has_alternate_ongoing_log_store() &&
184 alternate_ongoing_log_queue_->has_unsent_logs();
185 }
186
alternate_ongoing_log_store_has_staged_log() const187 bool MetricsLogStore::alternate_ongoing_log_store_has_staged_log() const {
188 return has_alternate_ongoing_log_store() &&
189 alternate_ongoing_log_queue_->has_staged_log();
190 }
191
GetLogStoreForLogType(MetricsLog::LogType log_type)192 UnsentLogStore* MetricsLogStore::GetLogStoreForLogType(
193 MetricsLog::LogType log_type) {
194 switch (log_type) {
195 case MetricsLog::INITIAL_STABILITY_LOG:
196 return &initial_log_queue_;
197 case MetricsLog::ONGOING_LOG:
198 case MetricsLog::INDEPENDENT_LOG:
199 return has_alternate_ongoing_log_store()
200 ? alternate_ongoing_log_queue_.get()
201 : &ongoing_log_queue_;
202 }
203 }
204
StageNextLog()205 void MetricsLogStore::StageNextLog() {
206 DCHECK(!has_staged_log());
207 if (initial_log_queue_.has_unsent_logs())
208 initial_log_queue_.StageNextLog();
209 else if (alternate_ongoing_log_store_has_unsent_logs())
210 alternate_ongoing_log_queue_->StageNextLog();
211 else if (ongoing_log_queue_.has_unsent_logs())
212 ongoing_log_queue_.StageNextLog();
213 }
214
DiscardStagedLog(std::string_view reason)215 void MetricsLogStore::DiscardStagedLog(std::string_view reason) {
216 DCHECK(has_staged_log());
217 if (initial_log_queue_.has_staged_log())
218 initial_log_queue_.DiscardStagedLog(reason);
219 else if (alternate_ongoing_log_store_has_staged_log())
220 alternate_ongoing_log_queue_->DiscardStagedLog(reason);
221 else if (ongoing_log_queue_.has_staged_log())
222 ongoing_log_queue_.DiscardStagedLog(reason);
223
224 DCHECK(!has_staged_log());
225 }
226
MarkStagedLogAsSent()227 void MetricsLogStore::MarkStagedLogAsSent() {
228 DCHECK(has_staged_log());
229 if (initial_log_queue_.has_staged_log())
230 initial_log_queue_.MarkStagedLogAsSent();
231 else if (alternate_ongoing_log_store_has_staged_log())
232 alternate_ongoing_log_queue_->MarkStagedLogAsSent();
233 else if (ongoing_log_queue_.has_staged_log())
234 ongoing_log_queue_.MarkStagedLogAsSent();
235 }
236
TrimAndPersistUnsentLogs(bool overwrite_in_memory_store)237 void MetricsLogStore::TrimAndPersistUnsentLogs(bool overwrite_in_memory_store) {
238 DCHECK(unsent_logs_loaded_);
239 if (!unsent_logs_loaded_)
240 return;
241
242 initial_log_queue_.TrimAndPersistUnsentLogs(overwrite_in_memory_store);
243 ongoing_log_queue_.TrimAndPersistUnsentLogs(overwrite_in_memory_store);
244 if (has_alternate_ongoing_log_store())
245 alternate_ongoing_log_queue_->TrimAndPersistUnsentLogs(
246 overwrite_in_memory_store);
247 }
248
249 } // namespace metrics
250