Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/metrics/metrics_log_manager.h" | 5 #include "components/metrics/metrics_log_store.h" |
| 6 | 6 |
| 7 #include <algorithm> | |
| 8 #include <utility> | |
| 9 | |
| 10 #include "base/strings/string_util.h" | |
| 11 #include "components/metrics/metrics_log.h" | |
| 12 #include "components/metrics/metrics_pref_names.h" | 7 #include "components/metrics/metrics_pref_names.h" |
| 13 #include "components/metrics/persisted_logs_metrics_impl.h" | 8 #include "components/metrics/persisted_logs_metrics_impl.h" |
| 9 #include "components/prefs/pref_registry_simple.h" | |
| 14 | 10 |
| 15 namespace metrics { | 11 namespace metrics { |
| 16 | 12 |
| 17 namespace { | 13 namespace { |
| 18 | 14 |
| 19 // The number of "initial" logs to save, and hope to send during a future Chrome | 15 // The number of "initial" logs to save, and hope to send during a future Chrome |
| 20 // session. Initial logs contain crash stats, and are pretty small. | 16 // session. Initial logs contain crash stats, and are pretty small. |
| 21 const size_t kInitialLogsPersistLimit = 20; | 17 const size_t kInitialLogsPersistLimit = 20; |
| 22 | 18 |
| 23 // The number of ongoing logs to save persistently, and hope to | 19 // The number of ongoing logs to save persistently, and hope to |
| 24 // send during a this or future sessions. Note that each log may be pretty | 20 // send during a this or future sessions. Note that each log may be pretty |
| 25 // large, as presumably the related "initial" log wasn't sent (probably nothing | 21 // large, as presumably the related "initial" log wasn't sent (probably nothing |
| 26 // was, as the user was probably off-line). As a result, the log probably kept | 22 // was, as the user was probably off-line). As a result, the log probably kept |
| 27 // accumulating while the "initial" log was stalled, and couldn't be sent. As a | 23 // accumulating while the "initial" log was stalled, and couldn't be sent. As a |
| 28 // result, we don't want to save too many of these mega-logs. | 24 // result, we don't want to save too many of these mega-logs. |
| 29 // A "standard shutdown" will create a small log, including just the data that | 25 // A "standard shutdown" will create a small log, including just the data that |
| 30 // was not yet been transmitted, and that is normal (to have exactly one | 26 // was not yet been transmitted, and that is normal (to have exactly one |
| 31 // ongoing_log_ at startup). | 27 // ongoing_log_ at startup). |
| 32 const size_t kOngoingLogsPersistLimit = 8; | 28 const size_t kOngoingLogsPersistLimit = 8; |
| 33 | 29 |
| 34 // The number of bytes each of initial and ongoing logs that must be stored. | 30 // The number of bytes of logs to save of each type (initial/ongoing). |
| 35 // This ensures that a reasonable amount of history will be stored even if there | 31 // This ensures that a reasonable amount of history will be stored even if there |
| 36 // is a long series of very small logs. | 32 // is a long series of very small logs. |
| 37 const size_t kStorageByteLimitPerLogType = 300000; | 33 const size_t kStorageByteLimitPerLogType = 300 * 1000; // ~300kB |
|
bcwhite
2017/02/22 16:25:09
How about: 300 << 10 // 300 KiB
Steven Holte
2017/02/22 20:35:50
I don't want to change behavior in this CL.
| |
| 38 | 34 |
| 39 } // namespace | 35 } // namespace |
| 40 | 36 |
| 41 MetricsLogManager::MetricsLogManager(PrefService* local_state, | 37 // static |
| 42 size_t max_ongoing_log_size) | 38 void MetricsLogStore::RegisterPrefs(PrefRegistrySimple* registry) { |
| 39 registry->RegisterListPref(prefs::kMetricsInitialLogs); | |
| 40 registry->RegisterListPref(prefs::kMetricsOngoingLogs); | |
| 41 } | |
| 42 | |
| 43 MetricsLogStore::MetricsLogStore(PrefService* local_state, size_t max_log_size) | |
| 43 : unsent_logs_loaded_(false), | 44 : unsent_logs_loaded_(false), |
| 44 initial_log_queue_(std::unique_ptr<PersistedLogsMetricsImpl>( | 45 initial_log_queue_(std::unique_ptr<PersistedLogsMetricsImpl>( |
| 45 new PersistedLogsMetricsImpl()), | 46 new PersistedLogsMetricsImpl()), |
| 46 local_state, | 47 local_state, |
| 47 prefs::kMetricsInitialLogs, | 48 prefs::kMetricsInitialLogs, |
| 48 kInitialLogsPersistLimit, | 49 kInitialLogsPersistLimit, |
| 49 kStorageByteLimitPerLogType, | 50 kStorageByteLimitPerLogType, |
| 50 0), | 51 0), |
| 51 ongoing_log_queue_(std::unique_ptr<PersistedLogsMetricsImpl>( | 52 ongoing_log_queue_(std::unique_ptr<PersistedLogsMetricsImpl>( |
| 52 new PersistedLogsMetricsImpl()), | 53 new PersistedLogsMetricsImpl()), |
| 53 local_state, | 54 local_state, |
| 54 prefs::kMetricsOngoingLogs, | 55 prefs::kMetricsOngoingLogs, |
| 55 kOngoingLogsPersistLimit, | 56 kOngoingLogsPersistLimit, |
| 56 kStorageByteLimitPerLogType, | 57 kStorageByteLimitPerLogType, |
| 57 max_ongoing_log_size) {} | 58 max_log_size) {} |
| 58 | 59 |
| 59 MetricsLogManager::~MetricsLogManager() {} | 60 MetricsLogStore::~MetricsLogStore() {} |
| 60 | 61 |
| 61 void MetricsLogManager::BeginLoggingWithLog(std::unique_ptr<MetricsLog> log) { | 62 void MetricsLogStore::LoadPersistedUnsentLogs() { |
| 62 DCHECK(!current_log_); | 63 initial_log_queue_.LoadPersistedUnsentLogs(); |
| 63 current_log_ = std::move(log); | 64 ongoing_log_queue_.LoadPersistedUnsentLogs(); |
| 65 unsent_logs_loaded_ = true; | |
| 64 } | 66 } |
| 65 | 67 |
| 66 void MetricsLogManager::FinishCurrentLog() { | 68 void MetricsLogStore::StoreLog(const std::string& log_data, |
| 67 DCHECK(current_log_.get()); | 69 MetricsLog::LogType log_type) { |
| 68 current_log_->CloseLog(); | |
| 69 std::string log_data; | |
| 70 current_log_->GetEncodedLog(&log_data); | |
| 71 if (!log_data.empty()) | |
| 72 StoreLog(log_data, current_log_->log_type()); | |
| 73 current_log_.reset(); | |
| 74 } | |
| 75 | |
| 76 void MetricsLogManager::StageNextLogForUpload() { | |
| 77 DCHECK(!has_staged_log()); | |
| 78 if (!initial_log_queue_.empty()) | |
| 79 initial_log_queue_.StageLog(); | |
| 80 else | |
| 81 ongoing_log_queue_.StageLog(); | |
| 82 } | |
| 83 | |
| 84 void MetricsLogManager::DiscardStagedLog() { | |
| 85 DCHECK(has_staged_log()); | |
| 86 if (initial_log_queue_.has_staged_log()) | |
| 87 initial_log_queue_.DiscardStagedLog(); | |
| 88 else | |
| 89 ongoing_log_queue_.DiscardStagedLog(); | |
| 90 DCHECK(!has_staged_log()); | |
| 91 } | |
| 92 | |
| 93 void MetricsLogManager::DiscardCurrentLog() { | |
| 94 current_log_->CloseLog(); | |
| 95 current_log_.reset(); | |
| 96 } | |
| 97 | |
| 98 void MetricsLogManager::PauseCurrentLog() { | |
| 99 DCHECK(!paused_log_.get()); | |
| 100 paused_log_ = std::move(current_log_); | |
| 101 } | |
| 102 | |
| 103 void MetricsLogManager::ResumePausedLog() { | |
| 104 DCHECK(!current_log_.get()); | |
| 105 current_log_ = std::move(paused_log_); | |
| 106 } | |
| 107 | |
| 108 void MetricsLogManager::StoreLog(const std::string& log_data, | |
| 109 MetricsLog::LogType log_type) { | |
| 110 switch (log_type) { | 70 switch (log_type) { |
| 111 case MetricsLog::INITIAL_STABILITY_LOG: | 71 case MetricsLog::INITIAL_STABILITY_LOG: |
| 112 initial_log_queue_.StoreLog(log_data); | 72 initial_log_queue_.StoreLog(log_data); |
| 113 break; | 73 break; |
| 114 case MetricsLog::ONGOING_LOG: | 74 case MetricsLog::ONGOING_LOG: |
| 115 ongoing_log_queue_.StoreLog(log_data); | 75 ongoing_log_queue_.StoreLog(log_data); |
| 116 break; | 76 break; |
| 117 } | 77 } |
| 118 } | 78 } |
| 119 | 79 |
| 120 void MetricsLogManager::PersistUnsentLogs() { | 80 bool MetricsLogStore::has_unsent_logs() const { |
| 81 return initial_log_queue_.has_unsent_logs() || | |
| 82 ongoing_log_queue_.has_unsent_logs(); | |
| 83 } | |
| 84 | |
| 85 bool MetricsLogStore::has_staged_log() const { | |
| 86 return initial_log_queue_.has_staged_log() || | |
| 87 ongoing_log_queue_.has_staged_log(); | |
| 88 } | |
| 89 | |
| 90 const std::string& MetricsLogStore::staged_log() const { | |
| 91 return initial_log_queue_.has_staged_log() ? initial_log_queue_.staged_log() | |
| 92 : ongoing_log_queue_.staged_log(); | |
| 93 } | |
| 94 | |
| 95 const std::string& MetricsLogStore::staged_log_hash() const { | |
| 96 return initial_log_queue_.has_staged_log() | |
| 97 ? initial_log_queue_.staged_log_hash() | |
| 98 : ongoing_log_queue_.staged_log_hash(); | |
| 99 } | |
| 100 | |
| 101 void MetricsLogStore::StageNextLog() { | |
| 102 DCHECK(!has_staged_log()); | |
| 103 if (initial_log_queue_.has_unsent_logs()) | |
| 104 initial_log_queue_.StageNextLog(); | |
| 105 else | |
| 106 ongoing_log_queue_.StageNextLog(); | |
| 107 } | |
| 108 | |
| 109 void MetricsLogStore::DiscardStagedLog() { | |
| 110 DCHECK(has_staged_log()); | |
| 111 if (initial_log_queue_.has_staged_log()) | |
| 112 initial_log_queue_.DiscardStagedLog(); | |
| 113 else | |
| 114 ongoing_log_queue_.DiscardStagedLog(); | |
| 115 DCHECK(!has_staged_log()); | |
| 116 } | |
| 117 | |
| 118 void MetricsLogStore::PersistUnsentLogs() const { | |
| 121 DCHECK(unsent_logs_loaded_); | 119 DCHECK(unsent_logs_loaded_); |
| 122 if (!unsent_logs_loaded_) | 120 if (!unsent_logs_loaded_) |
| 123 return; | 121 return; |
| 124 | 122 |
| 125 initial_log_queue_.SerializeLogs(); | 123 initial_log_queue_.PersistUnsentLogs(); |
| 126 ongoing_log_queue_.SerializeLogs(); | 124 ongoing_log_queue_.PersistUnsentLogs(); |
| 127 } | |
| 128 | |
| 129 void MetricsLogManager::LoadPersistedUnsentLogs() { | |
| 130 initial_log_queue_.DeserializeLogs(); | |
| 131 ongoing_log_queue_.DeserializeLogs(); | |
| 132 unsent_logs_loaded_ = true; | |
| 133 } | 125 } |
| 134 | 126 |
| 135 } // namespace metrics | 127 } // namespace metrics |
| OLD | NEW |