• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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