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