| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/persisted_logs.h" | 5 #include "components/metrics/persisted_logs.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 min_log_bytes_(min_log_bytes), | 70 min_log_bytes_(min_log_bytes), |
| 71 max_log_size_(max_log_size != 0 ? max_log_size : static_cast<size_t>(-1)), | 71 max_log_size_(max_log_size != 0 ? max_log_size : static_cast<size_t>(-1)), |
| 72 staged_log_index_(-1) { | 72 staged_log_index_(-1) { |
| 73 DCHECK(local_state_); | 73 DCHECK(local_state_); |
| 74 // One of the limit arguments must be non-zero. | 74 // One of the limit arguments must be non-zero. |
| 75 DCHECK(min_log_count_ > 0 || min_log_bytes_ > 0); | 75 DCHECK(min_log_count_ > 0 || min_log_bytes_ > 0); |
| 76 } | 76 } |
| 77 | 77 |
| 78 PersistedLogs::~PersistedLogs() {} | 78 PersistedLogs::~PersistedLogs() {} |
| 79 | 79 |
| 80 void PersistedLogs::SerializeLogs() const { | 80 bool PersistedLogs::has_unsent_logs() const { |
| 81 ListPrefUpdate update(local_state_, pref_name_); | 81 return !!size(); |
| 82 WriteLogsToPrefList(update.Get()); | |
| 83 } | 82 } |
| 84 | 83 |
| 85 PersistedLogs::LogReadStatus PersistedLogs::DeserializeLogs() { | 84 // True if a log has been staged. |
| 86 return ReadLogsFromPrefList(*local_state_->GetList(pref_name_)); | 85 bool PersistedLogs::has_staged_log() const { |
| 86 return staged_log_index_ != -1; |
| 87 } | 87 } |
| 88 | 88 |
| 89 void PersistedLogs::StoreLog(const std::string& log_data) { | 89 // Returns the element in the front of the list. |
| 90 list_.push_back(LogInfo()); | 90 const std::string& PersistedLogs::staged_log() const { |
| 91 list_.back().Init(metrics_.get(), | 91 DCHECK(has_staged_log()); |
| 92 log_data, | 92 return list_[staged_log_index_].compressed_log_data; |
| 93 base::Int64ToString(base::Time::Now().ToTimeT())); | |
| 94 } | 93 } |
| 95 | 94 |
| 96 void PersistedLogs::StageLog() { | 95 // Returns the element in the front of the list. |
| 96 const std::string& PersistedLogs::staged_log_hash() const { |
| 97 DCHECK(has_staged_log()); |
| 98 return list_[staged_log_index_].hash; |
| 99 } |
| 100 |
| 101 // Returns the timestamp of the element in the front of the list. |
| 102 const std::string& PersistedLogs::staged_log_timestamp() const { |
| 103 DCHECK(has_staged_log()); |
| 104 return list_[staged_log_index_].timestamp; |
| 105 } |
| 106 |
| 107 void PersistedLogs::StageNextLog() { |
| 97 // CHECK, rather than DCHECK, because swap()ing with an empty list causes | 108 // CHECK, rather than DCHECK, because swap()ing with an empty list causes |
| 98 // hard-to-identify crashes much later. | 109 // hard-to-identify crashes much later. |
| 99 CHECK(!list_.empty()); | 110 CHECK(!list_.empty()); |
| 100 DCHECK(!has_staged_log()); | 111 DCHECK(!has_staged_log()); |
| 101 staged_log_index_ = list_.size() - 1; | 112 staged_log_index_ = list_.size() - 1; |
| 102 DCHECK(has_staged_log()); | 113 DCHECK(has_staged_log()); |
| 103 } | 114 } |
| 104 | 115 |
| 105 void PersistedLogs::DiscardStagedLog() { | 116 void PersistedLogs::DiscardStagedLog() { |
| 106 DCHECK(has_staged_log()); | 117 DCHECK(has_staged_log()); |
| 107 DCHECK_LT(static_cast<size_t>(staged_log_index_), list_.size()); | 118 DCHECK_LT(static_cast<size_t>(staged_log_index_), list_.size()); |
| 108 list_.erase(list_.begin() + staged_log_index_); | 119 list_.erase(list_.begin() + staged_log_index_); |
| 109 staged_log_index_ = -1; | 120 staged_log_index_ = -1; |
| 110 } | 121 } |
| 111 | 122 |
| 123 void PersistedLogs::PersistUnsentLogs() const { |
| 124 ListPrefUpdate update(local_state_, pref_name_); |
| 125 WriteLogsToPrefList(update.Get()); |
| 126 } |
| 127 |
| 128 void PersistedLogs::LoadPersistedUnsentLogs() { |
| 129 ReadLogsFromPrefList(*local_state_->GetList(pref_name_)); |
| 130 } |
| 131 |
| 132 void PersistedLogs::StoreLog(const std::string& log_data) { |
| 133 list_.push_back(LogInfo()); |
| 134 list_.back().Init(metrics_.get(), log_data, |
| 135 base::Int64ToString(base::Time::Now().ToTimeT())); |
| 136 } |
| 137 |
| 112 void PersistedLogs::Purge() { | 138 void PersistedLogs::Purge() { |
| 113 if (has_staged_log()) { | 139 if (has_staged_log()) { |
| 114 DiscardStagedLog(); | 140 DiscardStagedLog(); |
| 115 } | 141 } |
| 116 list_.clear(); | 142 list_.clear(); |
| 117 local_state_->ClearPref(pref_name_); | 143 local_state_->ClearPref(pref_name_); |
| 118 } | 144 } |
| 119 | 145 |
| 120 PersistedLogs::LogReadStatus PersistedLogs::ReadLogsFromPrefList( | 146 void PersistedLogs::ReadLogsFromPrefList(const base::ListValue& list_value) { |
| 121 const base::ListValue& list_value) { | 147 if (list_value.empty()) { |
| 122 if (list_value.empty()) | 148 metrics_->RecordLogReadStatus(PersistedLogsMetrics::LIST_EMPTY); |
| 123 return metrics_->RecordLogReadStatus(LIST_EMPTY); | 149 return; |
| 150 } |
| 124 | 151 |
| 125 const size_t log_count = list_value.GetSize(); | 152 const size_t log_count = list_value.GetSize(); |
| 126 | 153 |
| 127 DCHECK(list_.empty()); | 154 DCHECK(list_.empty()); |
| 128 list_.resize(log_count); | 155 list_.resize(log_count); |
| 129 | 156 |
| 130 for (size_t i = 0; i < log_count; ++i) { | 157 for (size_t i = 0; i < log_count; ++i) { |
| 131 const base::DictionaryValue* dict; | 158 const base::DictionaryValue* dict; |
| 132 if (!list_value.GetDictionary(i, &dict) || | 159 if (!list_value.GetDictionary(i, &dict) || |
| 133 !dict->GetString(kLogDataKey, &list_[i].compressed_log_data) || | 160 !dict->GetString(kLogDataKey, &list_[i].compressed_log_data) || |
| 134 !dict->GetString(kLogHashKey, &list_[i].hash)) { | 161 !dict->GetString(kLogHashKey, &list_[i].hash)) { |
| 135 list_.clear(); | 162 list_.clear(); |
| 136 return metrics_->RecordLogReadStatus(LOG_STRING_CORRUPTION); | 163 metrics_->RecordLogReadStatus( |
| 164 PersistedLogsMetrics::LOG_STRING_CORRUPTION); |
| 165 return; |
| 137 } | 166 } |
| 138 | 167 |
| 139 list_[i].compressed_log_data = | 168 list_[i].compressed_log_data = |
| 140 DecodeFromBase64(list_[i].compressed_log_data); | 169 DecodeFromBase64(list_[i].compressed_log_data); |
| 141 list_[i].hash = DecodeFromBase64(list_[i].hash); | 170 list_[i].hash = DecodeFromBase64(list_[i].hash); |
| 142 // Ignoring the success of this step as timestamp might not be there for | 171 // Ignoring the success of this step as timestamp might not be there for |
| 143 // older logs. | 172 // older logs. |
| 144 // NOTE: Should be added to the check with other fields once migration is | 173 // NOTE: Should be added to the check with other fields once migration is |
| 145 // over. | 174 // over. |
| 146 dict->GetString(kLogTimestampKey, &list_[i].timestamp); | 175 dict->GetString(kLogTimestampKey, &list_[i].timestamp); |
| 147 } | 176 } |
| 148 | 177 |
| 149 return metrics_->RecordLogReadStatus(RECALL_SUCCESS); | 178 metrics_->RecordLogReadStatus(PersistedLogsMetrics::RECALL_SUCCESS); |
| 150 } | 179 } |
| 151 | 180 |
| 152 void PersistedLogs::WriteLogsToPrefList(base::ListValue* list_value) const { | 181 void PersistedLogs::WriteLogsToPrefList(base::ListValue* list_value) const { |
| 153 list_value->Clear(); | 182 list_value->Clear(); |
| 154 | 183 |
| 155 // Keep the most recent logs which are smaller than |max_log_size_|. | 184 // Keep the most recent logs which are smaller than |max_log_size_|. |
| 156 // We keep at least |min_log_bytes_| and |min_log_count_| of logs before | 185 // We keep at least |min_log_bytes_| and |min_log_count_| of logs before |
| 157 // discarding older logs. | 186 // discarding older logs. |
| 158 size_t start = list_.size(); | 187 size_t start = list_.size(); |
| 159 size_t saved_log_count = 0; | 188 size_t saved_log_count = 0; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 185 dict_value->SetString(kLogDataKey, | 214 dict_value->SetString(kLogDataKey, |
| 186 EncodeToBase64(list_[i].compressed_log_data)); | 215 EncodeToBase64(list_[i].compressed_log_data)); |
| 187 dict_value->SetString(kLogTimestampKey, list_[i].timestamp); | 216 dict_value->SetString(kLogTimestampKey, list_[i].timestamp); |
| 188 list_value->Append(std::move(dict_value)); | 217 list_value->Append(std::move(dict_value)); |
| 189 } | 218 } |
| 190 if (dropped_logs_num > 0) | 219 if (dropped_logs_num > 0) |
| 191 metrics_->RecordDroppedLogsNum(dropped_logs_num); | 220 metrics_->RecordDroppedLogsNum(dropped_logs_num); |
| 192 } | 221 } |
| 193 | 222 |
| 194 } // namespace metrics | 223 } // namespace metrics |
| OLD | NEW |