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_(std::make_unique<UnsentLogStoreMetricsImpl>(),
29 local_state,
30 prefs::kMetricsInitialLogs,
31 prefs::kMetricsInitialLogsMetadata,
32 storage_limits.min_initial_log_queue_count,
33 storage_limits.min_initial_log_queue_size,
34 0, // Each individual initial log can be any size.
35 signing_key,
36 logs_event_manager),
37 ongoing_log_queue_(std::make_unique<UnsentLogStoreMetricsImpl>(),
38 local_state,
39 prefs::kMetricsOngoingLogs,
40 prefs::kMetricsOngoingLogsMetadata,
41 storage_limits.min_ongoing_log_queue_count,
42 storage_limits.min_ongoing_log_queue_size,
43 storage_limits.max_ongoing_log_size,
44 signing_key,
45 logs_event_manager) {}
46
~MetricsLogStore()47 MetricsLogStore::~MetricsLogStore() {}
48
LoadPersistedUnsentLogs()49 void MetricsLogStore::LoadPersistedUnsentLogs() {
50 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
51
52 {
53 MetricsLogsEventManager::ScopedNotifyLogType scoped_log_type(
54 logs_event_manager_, MetricsLog::LogType::INITIAL_STABILITY_LOG);
55 initial_log_queue_.LoadPersistedUnsentLogs();
56 }
57
58 {
59 // Note that we assume that logs loaded from the persistent storage for
60 // |ongoing_log_queue_| are of type "ongoing". They could, however, be
61 // independent logs, but we unfortunately cannot determine this since we
62 // don't persist the type of log.
63 MetricsLogsEventManager::ScopedNotifyLogType scoped_log_type(
64 logs_event_manager_, MetricsLog::LogType::ONGOING_LOG);
65 ongoing_log_queue_.LoadPersistedUnsentLogs();
66 }
67
68 unsent_logs_loaded_ = true;
69 }
70
StoreLog(const std::string & log_data,MetricsLog::LogType log_type,const LogMetadata & log_metadata,MetricsLogsEventManager::CreateReason reason)71 void MetricsLogStore::StoreLog(const std::string& log_data,
72 MetricsLog::LogType log_type,
73 const LogMetadata& log_metadata,
74 MetricsLogsEventManager::CreateReason reason) {
75 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
76
77 MetricsLogsEventManager::ScopedNotifyLogType scoped_log_type(
78 logs_event_manager_, log_type);
79 GetLogStoreForLogType(log_type)->StoreLog(log_data, log_metadata, reason);
80 }
81
StoreLogInfo(std::unique_ptr<UnsentLogStore::LogInfo> log_info,size_t uncompressed_log_size,MetricsLog::LogType log_type,MetricsLogsEventManager::CreateReason reason)82 void MetricsLogStore::StoreLogInfo(
83 std::unique_ptr<UnsentLogStore::LogInfo> log_info,
84 size_t uncompressed_log_size,
85 MetricsLog::LogType log_type,
86 MetricsLogsEventManager::CreateReason reason) {
87 MetricsLogsEventManager::ScopedNotifyLogType scoped_log_type(
88 logs_event_manager_, log_type);
89 GetLogStoreForLogType(log_type)->StoreLogInfo(std::move(log_info),
90 uncompressed_log_size, reason);
91 }
92
Purge()93 void MetricsLogStore::Purge() {
94 initial_log_queue_.Purge();
95 ongoing_log_queue_.Purge();
96 if (has_alternate_ongoing_log_store()) {
97 alternate_ongoing_log_queue_->Purge();
98 }
99 }
100
GetSigningKeyForLogType(MetricsLog::LogType log_type)101 const std::string& MetricsLogStore::GetSigningKeyForLogType(
102 MetricsLog::LogType log_type) {
103 return GetLogStoreForLogType(log_type)->signing_key();
104 }
105
SetAlternateOngoingLogStore(std::unique_ptr<UnsentLogStore> log_store)106 void MetricsLogStore::SetAlternateOngoingLogStore(
107 std::unique_ptr<UnsentLogStore> log_store) {
108 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
109
110 DCHECK(!has_alternate_ongoing_log_store());
111 DCHECK(unsent_logs_loaded_);
112 alternate_ongoing_log_queue_ = std::move(log_store);
113 alternate_ongoing_log_queue_->SetLogsEventManager(logs_event_manager_);
114
115 // Note that we assume that logs loaded from the persistent storage for
116 // |alternate_ongoing_log_queue_| are of type "ongoing". They could, however,
117 // be independent logs, but we unfortunately cannot determine this since we
118 // don't persist the type of log.
119 MetricsLogsEventManager::ScopedNotifyLogType scoped_log_type(
120 logs_event_manager_, MetricsLog::LogType::ONGOING_LOG);
121 alternate_ongoing_log_queue_->LoadPersistedUnsentLogs();
122 }
123
UnsetAlternateOngoingLogStore()124 void MetricsLogStore::UnsetAlternateOngoingLogStore() {
125 DCHECK(has_alternate_ongoing_log_store());
126 alternate_ongoing_log_queue_->TrimAndPersistUnsentLogs(
127 /*overwrite_in_memory_store=*/true);
128 alternate_ongoing_log_queue_.reset();
129 }
130
has_unsent_logs() const131 bool MetricsLogStore::has_unsent_logs() const {
132 return initial_log_queue_.has_unsent_logs() ||
133 ongoing_log_queue_.has_unsent_logs() ||
134 alternate_ongoing_log_store_has_unsent_logs();
135 }
136
has_staged_log() const137 bool MetricsLogStore::has_staged_log() const {
138 return initial_log_queue_.has_staged_log() ||
139 ongoing_log_queue_.has_staged_log() ||
140 alternate_ongoing_log_store_has_staged_log();
141 }
142
staged_log() const143 const std::string& MetricsLogStore::staged_log() const {
144 return get_staged_log_queue()->staged_log();
145 }
146
staged_log_hash() const147 const std::string& MetricsLogStore::staged_log_hash() const {
148 return get_staged_log_queue()->staged_log_hash();
149 }
150
staged_log_signature() const151 const std::string& MetricsLogStore::staged_log_signature() const {
152 return get_staged_log_queue()->staged_log_signature();
153 }
154
staged_log_user_id() const155 absl::optional<uint64_t> MetricsLogStore::staged_log_user_id() const {
156 return get_staged_log_queue()->staged_log_user_id();
157 }
158
has_alternate_ongoing_log_store() const159 bool MetricsLogStore::has_alternate_ongoing_log_store() const {
160 return alternate_ongoing_log_queue_ != nullptr;
161 }
162
get_staged_log_queue() const163 const UnsentLogStore* MetricsLogStore::get_staged_log_queue() const {
164 DCHECK(has_staged_log());
165
166 // This is the order in which logs should be staged. Should be consistent with
167 // StageNextLog.
168 if (initial_log_queue_.has_staged_log())
169 return &initial_log_queue_;
170 else if (alternate_ongoing_log_store_has_staged_log())
171 return alternate_ongoing_log_queue_.get();
172 return &ongoing_log_queue_;
173 }
174
alternate_ongoing_log_store_has_unsent_logs() const175 bool MetricsLogStore::alternate_ongoing_log_store_has_unsent_logs() const {
176 return has_alternate_ongoing_log_store() &&
177 alternate_ongoing_log_queue_->has_unsent_logs();
178 }
179
alternate_ongoing_log_store_has_staged_log() const180 bool MetricsLogStore::alternate_ongoing_log_store_has_staged_log() const {
181 return has_alternate_ongoing_log_store() &&
182 alternate_ongoing_log_queue_->has_staged_log();
183 }
184
GetLogStoreForLogType(MetricsLog::LogType log_type)185 UnsentLogStore* MetricsLogStore::GetLogStoreForLogType(
186 MetricsLog::LogType log_type) {
187 switch (log_type) {
188 case MetricsLog::INITIAL_STABILITY_LOG:
189 return &initial_log_queue_;
190 case MetricsLog::ONGOING_LOG:
191 case MetricsLog::INDEPENDENT_LOG:
192 return has_alternate_ongoing_log_store()
193 ? alternate_ongoing_log_queue_.get()
194 : &ongoing_log_queue_;
195 }
196 }
197
StageNextLog()198 void MetricsLogStore::StageNextLog() {
199 DCHECK(!has_staged_log());
200 if (initial_log_queue_.has_unsent_logs())
201 initial_log_queue_.StageNextLog();
202 else if (alternate_ongoing_log_store_has_unsent_logs())
203 alternate_ongoing_log_queue_->StageNextLog();
204 else if (ongoing_log_queue_.has_unsent_logs())
205 ongoing_log_queue_.StageNextLog();
206 }
207
DiscardStagedLog(base::StringPiece reason)208 void MetricsLogStore::DiscardStagedLog(base::StringPiece reason) {
209 DCHECK(has_staged_log());
210 if (initial_log_queue_.has_staged_log())
211 initial_log_queue_.DiscardStagedLog(reason);
212 else if (alternate_ongoing_log_store_has_staged_log())
213 alternate_ongoing_log_queue_->DiscardStagedLog(reason);
214 else if (ongoing_log_queue_.has_staged_log())
215 ongoing_log_queue_.DiscardStagedLog(reason);
216
217 DCHECK(!has_staged_log());
218 }
219
MarkStagedLogAsSent()220 void MetricsLogStore::MarkStagedLogAsSent() {
221 DCHECK(has_staged_log());
222 if (initial_log_queue_.has_staged_log())
223 initial_log_queue_.MarkStagedLogAsSent();
224 else if (alternate_ongoing_log_store_has_staged_log())
225 alternate_ongoing_log_queue_->MarkStagedLogAsSent();
226 else if (ongoing_log_queue_.has_staged_log())
227 ongoing_log_queue_.MarkStagedLogAsSent();
228 }
229
TrimAndPersistUnsentLogs(bool overwrite_in_memory_store)230 void MetricsLogStore::TrimAndPersistUnsentLogs(bool overwrite_in_memory_store) {
231 DCHECK(unsent_logs_loaded_);
232 if (!unsent_logs_loaded_)
233 return;
234
235 initial_log_queue_.TrimAndPersistUnsentLogs(overwrite_in_memory_store);
236 ongoing_log_queue_.TrimAndPersistUnsentLogs(overwrite_in_memory_store);
237 if (has_alternate_ongoing_log_store())
238 alternate_ongoing_log_queue_->TrimAndPersistUnsentLogs(
239 overwrite_in_memory_store);
240 }
241
242 } // namespace metrics
243