Chromium Code Reviews| Index: chrome/browser/metrics/metrics_log_serializer.cc |
| diff --git a/chrome/browser/metrics/metrics_log_serializer.cc b/chrome/browser/metrics/metrics_log_serializer.cc |
| index bbddf601eb77710ae0e2ea2fae460a83c747425f..da375fe6730f50a97d859a546c9186c804bb9943 100644 |
| --- a/chrome/browser/metrics/metrics_log_serializer.cc |
| +++ b/chrome/browser/metrics/metrics_log_serializer.cc |
| @@ -4,6 +4,8 @@ |
| #include "chrome/browser/metrics/metrics_log_serializer.h" |
| +#include <utility> |
| + |
| #include "base/base64.h" |
| #include "base/md5.h" |
| #include "base/metrics/histogram.h" |
| @@ -12,10 +14,12 @@ |
| #include "chrome/browser/prefs/scoped_user_pref_update.h" |
| #include "chrome/common/pref_names.h" |
| +namespace { |
| + |
| // The number of "initial" logs we're willing to save, and hope to send during |
| // a future Chrome session. Initial logs contain crash stats, and are pretty |
| // small. |
| -static const size_t kMaxInitialLogsPersisted = 20; |
| +const size_t kMaxInitialLogsPersisted = 20; |
|
jar (doing other things)
2012/02/23 01:59:18
We should really have a style guide opinion for us
ian fette
2012/02/23 02:08:43
"Unnamed namespaces are allowed and even encourage
jar (doing other things)
2012/02/23 03:03:06
You missed my point (or perhaps I stated it poorly
Ilya Sherman
2012/02/24 02:10:06
I think the relevant style guide rule is this one:
|
| // The number of ongoing logs we're willing to save persistently, and hope to |
| // send during a this or future sessions. Note that each log may be pretty |
| @@ -26,15 +30,14 @@ static const size_t kMaxInitialLogsPersisted = 20; |
| // A "standard shutdown" will create a small log, including just the data that |
| // was not yet been transmitted, and that is normal (to have exactly one |
| // ongoing_log_ at startup). |
| -static const size_t kMaxOngoingLogsPersisted = 8; |
| +const size_t kMaxOngoingLogsPersisted = 8; |
| // We append (2) more elements to persisted lists: the size of the list and a |
| // checksum of the elements. |
| -static const size_t kChecksumEntryCount = 2; |
| +const size_t kChecksumEntryCount = 2; |
| -namespace { |
| -// TODO(ziadh): This is here temporarily for a side experiment. Remove later |
| -// on. |
| +// TODO(isherman): Remove this histogram once it's confirmed that there are no |
| +// encoding failures for protobuf logs. |
| enum LogStoreStatus { |
| STORE_SUCCESS, // Successfully presisted log. |
| ENCODE_FAIL, // Failed to encode log. |
| @@ -43,17 +46,23 @@ enum LogStoreStatus { |
| }; |
| MetricsLogSerializer::LogReadStatus MakeRecallStatusHistogram( |
| - MetricsLogSerializer::LogReadStatus status) { |
| - UMA_HISTOGRAM_ENUMERATION("PrefService.PersistentLogRecall", status, |
| - MetricsLogSerializer::END_RECALL_STATUS); |
| + MetricsLogSerializer::LogReadStatus status, |
| + bool is_xml) { |
| + if (is_xml) { |
| + UMA_HISTOGRAM_ENUMERATION("PrefService.PersistentLogRecall", |
| + status, MetricsLogSerializer::END_RECALL_STATUS); |
| + } else { |
| + UMA_HISTOGRAM_ENUMERATION("PrefService.PersistentLogRecallProtobufs", |
| + status, MetricsLogSerializer::END_RECALL_STATUS); |
| + } |
| return status; |
| } |
| -// TODO(ziadh): Remove this when done with experiment. |
| void MakeStoreStatusHistogram(LogStoreStatus status) { |
| UMA_HISTOGRAM_ENUMERATION("PrefService.PersistentLogStore2", status, |
| END_STORE_STATUS); |
| } |
| + |
| } // namespace |
| @@ -61,40 +70,84 @@ MetricsLogSerializer::MetricsLogSerializer() {} |
| MetricsLogSerializer::~MetricsLogSerializer() {} |
| -void MetricsLogSerializer::SerializeLogs(const std::vector<std::string>& logs, |
| - MetricsLogManager::LogType log_type) { |
| +void MetricsLogSerializer::SerializeLogs( |
| + const std::vector<std::pair<std::string, std::string> >& logs, |
|
jar (doing other things)
2012/02/23 01:59:18
This makes it clearer (reading the code) what the
|
| + MetricsLogManager::LogType log_type) { |
| PrefService* local_state = g_browser_process->local_state(); |
| DCHECK(local_state); |
| - const char* pref = NULL; |
| + const char* pref_xml = NULL; |
| + const char* pref_proto = NULL; |
| size_t max_store_count = 0; |
| switch (log_type) { |
| case MetricsLogManager::INITIAL_LOG: |
| - pref = prefs::kMetricsInitialLogs; |
| + pref_xml = prefs::kMetricsInitialLogsXml; |
| + pref_proto = prefs::kMetricsInitialLogsProto; |
| max_store_count = kMaxInitialLogsPersisted; |
| break; |
| case MetricsLogManager::ONGOING_LOG: |
| - pref = prefs::kMetricsOngoingLogs; |
| + pref_xml = prefs::kMetricsOngoingLogsXml; |
| + pref_proto = prefs::kMetricsOngoingLogsProto; |
| max_store_count = kMaxOngoingLogsPersisted; |
| break; |
| default: |
| NOTREACHED(); |
| return; |
| }; |
| - ListPrefUpdate update(local_state, pref); |
| - ListValue* pref_list = update.Get(); |
| - WriteLogsToPrefList(logs, max_store_count, pref_list); |
| + |
| + std::vector<std::string> logs_xml(logs.size()); |
| + std::vector<std::string> logs_proto(logs.size()); |
| + for (size_t i = 0; i < logs.size(); ++i) { |
| + logs_xml[i] = logs[i].first; |
|
jar (doing other things)
2012/02/23 01:59:18
These logs get to be big.... so this copying of st
ian fette
2012/02/23 02:08:43
std::strings are copy on write. Creating this sort
ian fette
2012/02/23 03:02:53
actually, rsleevi reminds me that after GCC 4.6, s
jar (doing other things)
2012/02/23 03:03:06
As noted by Sleevi, this copy-on-write semantic (r
Ryan Sleevi
2012/02/23 03:28:06
The relevant item from C++11 that I mentioned was
Ilya Sherman
2012/02/24 02:10:06
No longer copying the strings needlessly.
|
| + logs_proto[i] = logs[i].second; |
| + } |
| + |
| + // Write the XML version. |
| + ListPrefUpdate update_xml(local_state, pref_xml); |
| + ListValue* pref_list_xml = update_xml.Get(); |
| + WriteLogsToPrefList(logs_xml, max_store_count, pref_list_xml); |
| + |
| + // Write the protobuf version. |
| + ListPrefUpdate update_proto(local_state, pref_proto); |
| + ListValue* pref_list_proto = update_proto.Get(); |
| + WriteLogsToPrefList(logs_proto, max_store_count, pref_list_proto); |
| } |
| -void MetricsLogSerializer::DeserializeLogs(MetricsLogManager::LogType log_type, |
| - std::vector<std::string>* logs) { |
| +void MetricsLogSerializer::DeserializeLogs( |
| + MetricsLogManager::LogType log_type, |
| + std::vector<std::pair<std::string, std::string> >* logs) { |
| DCHECK(logs); |
| PrefService* local_state = g_browser_process->local_state(); |
| DCHECK(local_state); |
| - const char* pref = (log_type == MetricsLogManager::INITIAL_LOG) ? |
| - prefs::kMetricsInitialLogs : prefs::kMetricsOngoingLogs; |
| - const ListValue* unsent_logs = local_state->GetList(pref); |
| - ReadLogsFromPrefList(*unsent_logs, logs); |
| + const char* pref_xml; |
| + const char* pref_proto; |
| + if (log_type == MetricsLogManager::INITIAL_LOG) { |
| + pref_xml = prefs::kMetricsInitialLogsXml; |
| + pref_proto = prefs::kMetricsInitialLogsProto; |
| + } else { |
| + pref_xml = prefs::kMetricsOngoingLogsXml; |
| + pref_proto = prefs::kMetricsOngoingLogsProto; |
| + } |
| + |
| + const ListValue* unsent_logs_xml = local_state->GetList(pref_xml); |
| + const ListValue* unsent_logs_proto = local_state->GetList(pref_proto); |
| + std::vector<std::string> logs_xml; |
| + std::vector<std::string> logs_proto; |
| + if (ReadLogsFromPrefList(*unsent_logs_xml, true, &logs_xml) != RECALL_SUCCESS) |
| + return; |
| + if (ReadLogsFromPrefList(*unsent_logs_proto, false, &logs_proto) != |
| + RECALL_SUCCESS) |
| + return; |
| + |
| + if (logs_xml.size() != logs_proto.size()) { |
| + MakeRecallStatusHistogram(XML_PROTO_MISMATCH, false); |
| + return; |
| + } |
| + |
| + logs->resize(logs_xml.size()); |
| + for (size_t i = 0; i < logs->size(); ++i) { |
| + (*logs)[i] = std::make_pair(logs_xml[i], logs_proto[i]); |
| + } |
| } |
| // static |
| @@ -106,7 +159,7 @@ void MetricsLogSerializer::WriteLogsToPrefList( |
| size_t start = 0; |
| if (local_list.size() > kMaxLocalListSize) |
| start = local_list.size() - kMaxLocalListSize; |
| - DCHECK(start <= local_list.size()); |
| + DCHECK_LE(start, local_list.size()); |
| if (local_list.size() <= start) |
| return; |
| @@ -140,23 +193,24 @@ void MetricsLogSerializer::WriteLogsToPrefList( |
| // static |
| MetricsLogSerializer::LogReadStatus MetricsLogSerializer::ReadLogsFromPrefList( |
| const ListValue& list, |
| + bool is_xml, |
| std::vector<std::string>* local_list) { |
| DCHECK(local_list->empty()); |
| if (list.GetSize() == 0) |
| - return MakeRecallStatusHistogram(LIST_EMPTY); |
| + return MakeRecallStatusHistogram(LIST_EMPTY, is_xml); |
| if (list.GetSize() < 3) |
| - return MakeRecallStatusHistogram(LIST_SIZE_TOO_SMALL); |
| + return MakeRecallStatusHistogram(LIST_SIZE_TOO_SMALL, is_xml); |
| // The size is stored at the beginning of the list. |
| int size; |
| bool valid = (*list.begin())->GetAsInteger(&size); |
| if (!valid) |
| - return MakeRecallStatusHistogram(LIST_SIZE_MISSING); |
| + return MakeRecallStatusHistogram(LIST_SIZE_MISSING, is_xml); |
| // Account for checksum and size included in the list. |
| if (static_cast<unsigned int>(size) != |
| list.GetSize() - kChecksumEntryCount) { |
| - return MakeRecallStatusHistogram(LIST_SIZE_CORRUPTION); |
| + return MakeRecallStatusHistogram(LIST_SIZE_CORRUPTION, is_xml); |
| } |
| base::MD5Context ctx; |
| @@ -168,14 +222,14 @@ MetricsLogSerializer::LogReadStatus MetricsLogSerializer::ReadLogsFromPrefList( |
| valid = (*it)->GetAsString(&encoded_log); |
| if (!valid) { |
| local_list->clear(); |
| - return MakeRecallStatusHistogram(LOG_STRING_CORRUPTION); |
| + return MakeRecallStatusHistogram(LOG_STRING_CORRUPTION, is_xml); |
| } |
| base::MD5Update(&ctx, encoded_log); |
| if (!base::Base64Decode(encoded_log, &decoded_log)) { |
| local_list->clear(); |
| - return MakeRecallStatusHistogram(DECODE_FAIL); |
| + return MakeRecallStatusHistogram(DECODE_FAIL, is_xml); |
| } |
| local_list->push_back(decoded_log); |
| } |
| @@ -188,11 +242,11 @@ MetricsLogSerializer::LogReadStatus MetricsLogSerializer::ReadLogsFromPrefList( |
| valid = (*(list.end() - 1))->GetAsString(&recovered_md5); |
| if (!valid) { |
| local_list->clear(); |
| - return MakeRecallStatusHistogram(CHECKSUM_STRING_CORRUPTION); |
| + return MakeRecallStatusHistogram(CHECKSUM_STRING_CORRUPTION, is_xml); |
| } |
| if (recovered_md5 != base::MD5DigestToBase16(digest)) { |
| local_list->clear(); |
| - return MakeRecallStatusHistogram(CHECKSUM_CORRUPTION); |
| + return MakeRecallStatusHistogram(CHECKSUM_CORRUPTION, is_xml); |
| } |
| - return MakeRecallStatusHistogram(RECALL_SUCCESS); |
| + return MakeRecallStatusHistogram(RECALL_SUCCESS, is_xml); |
| } |