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.
5 #include "components/metrics/metrics_log_store.h"
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"
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);
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),
29 std::make_unique<UnsentLogStoreMetricsImpl>(),
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},
40 ongoing_log_queue_(std::make_unique<UnsentLogStoreMetricsImpl>(),
42 prefs::kMetricsOngoingLogs,
43 prefs::kMetricsOngoingLogsMetadata,
44 storage_limits.ongoing_log_queue_limits,
46 logs_event_manager) {}
48 MetricsLogStore::~MetricsLogStore() {}
50 void MetricsLogStore::LoadPersistedUnsentLogs() {
51 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
54 MetricsLogsEventManager::ScopedNotifyLogType scoped_log_type(
55 logs_event_manager_, MetricsLog::LogType::INITIAL_STABILITY_LOG);
56 initial_log_queue_.LoadPersistedUnsentLogs();
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();
69 unsent_logs_loaded_ = true;
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_);
78 MetricsLogsEventManager::ScopedNotifyLogType scoped_log_type(
79 logs_event_manager_, log_type);
80 GetLogStoreForLogType(log_type)->StoreLog(log_data, log_metadata, 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);
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();
102 const std::string& MetricsLogStore::GetSigningKeyForLogType(
103 MetricsLog::LogType log_type) {
104 return GetLogStoreForLogType(log_type)->signing_key();
107 void MetricsLogStore::SetAlternateOngoingLogStore(
108 std::unique_ptr<UnsentLogStore> log_store) {
109 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
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_);
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();
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();
132 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();
138 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();
144 const std::string& MetricsLogStore::staged_log() const {
145 return get_staged_log_queue()->staged_log();
148 const std::string& MetricsLogStore::staged_log_hash() const {
149 return get_staged_log_queue()->staged_log_hash();
152 const std::string& MetricsLogStore::staged_log_signature() const {
153 return get_staged_log_queue()->staged_log_signature();
156 absl::optional<uint64_t> MetricsLogStore::staged_log_user_id() const {
157 return get_staged_log_queue()->staged_log_user_id();
160 bool MetricsLogStore::has_alternate_ongoing_log_store() const {
161 return alternate_ongoing_log_queue_ != nullptr;
164 const UnsentLogStore* MetricsLogStore::get_staged_log_queue() const {
165 DCHECK(has_staged_log());
167 // This is the order in which logs should be staged. Should be consistent with
169 if (initial_log_queue_.has_staged_log())
170 return &initial_log_queue_;
171 else if (alternate_ongoing_log_store_has_staged_log())
172 return alternate_ongoing_log_queue_.get();
173 return &ongoing_log_queue_;
176 bool MetricsLogStore::alternate_ongoing_log_store_has_unsent_logs() const {
177 return has_alternate_ongoing_log_store() &&
178 alternate_ongoing_log_queue_->has_unsent_logs();
181 bool MetricsLogStore::alternate_ongoing_log_store_has_staged_log() const {
182 return has_alternate_ongoing_log_store() &&
183 alternate_ongoing_log_queue_->has_staged_log();
186 UnsentLogStore* MetricsLogStore::GetLogStoreForLogType(
187 MetricsLog::LogType log_type) {
189 case MetricsLog::INITIAL_STABILITY_LOG:
190 return &initial_log_queue_;
191 case MetricsLog::ONGOING_LOG:
192 case MetricsLog::INDEPENDENT_LOG:
193 return has_alternate_ongoing_log_store()
194 ? alternate_ongoing_log_queue_.get()
195 : &ongoing_log_queue_;
199 void MetricsLogStore::StageNextLog() {
200 DCHECK(!has_staged_log());
201 if (initial_log_queue_.has_unsent_logs())
202 initial_log_queue_.StageNextLog();
203 else if (alternate_ongoing_log_store_has_unsent_logs())
204 alternate_ongoing_log_queue_->StageNextLog();
205 else if (ongoing_log_queue_.has_unsent_logs())
206 ongoing_log_queue_.StageNextLog();
209 void MetricsLogStore::DiscardStagedLog(base::StringPiece reason) {
210 DCHECK(has_staged_log());
211 if (initial_log_queue_.has_staged_log())
212 initial_log_queue_.DiscardStagedLog(reason);
213 else if (alternate_ongoing_log_store_has_staged_log())
214 alternate_ongoing_log_queue_->DiscardStagedLog(reason);
215 else if (ongoing_log_queue_.has_staged_log())
216 ongoing_log_queue_.DiscardStagedLog(reason);
218 DCHECK(!has_staged_log());
221 void MetricsLogStore::MarkStagedLogAsSent() {
222 DCHECK(has_staged_log());
223 if (initial_log_queue_.has_staged_log())
224 initial_log_queue_.MarkStagedLogAsSent();
225 else if (alternate_ongoing_log_store_has_staged_log())
226 alternate_ongoing_log_queue_->MarkStagedLogAsSent();
227 else if (ongoing_log_queue_.has_staged_log())
228 ongoing_log_queue_.MarkStagedLogAsSent();
231 void MetricsLogStore::TrimAndPersistUnsentLogs(bool overwrite_in_memory_store) {
232 DCHECK(unsent_logs_loaded_);
233 if (!unsent_logs_loaded_)
236 initial_log_queue_.TrimAndPersistUnsentLogs(overwrite_in_memory_store);
237 ongoing_log_queue_.TrimAndPersistUnsentLogs(overwrite_in_memory_store);
238 if (has_alternate_ongoing_log_store())
239 alternate_ongoing_log_queue_->TrimAndPersistUnsentLogs(
240 overwrite_in_memory_store);
243 } // namespace metrics