Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Unified Diff: chrome/browser/metrics/metrics_log_serializer.cc

Issue 9232071: Upload UMA data using protocol buffers. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..3369f85a7a630d2fb4048732e554a3b5d0a8c320 100644
--- a/chrome/browser/metrics/metrics_log_serializer.cc
+++ b/chrome/browser/metrics/metrics_log_serializer.cc
@@ -12,10 +12,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;
// 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 +28,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 +44,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,52 +68,76 @@ MetricsLogSerializer::MetricsLogSerializer() {}
MetricsLogSerializer::~MetricsLogSerializer() {}
-void MetricsLogSerializer::SerializeLogs(const std::vector<std::string>& logs,
- MetricsLogManager::LogType log_type) {
+void MetricsLogSerializer::SerializeLogs(
+ const std::vector<MetricsLogManager::SerializedLog>& logs,
+ 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);
+
+ // Write the XML version.
+ ListPrefUpdate update_xml(local_state, pref_xml);
+ WriteLogsToPrefList(logs, true, max_store_count, update_xml.Get());
+
+ // Write the protobuf version.
+ ListPrefUpdate update_proto(local_state, pref_proto);
+ WriteLogsToPrefList(logs, false, max_store_count, update_proto.Get());
}
-void MetricsLogSerializer::DeserializeLogs(MetricsLogManager::LogType log_type,
- std::vector<std::string>* logs) {
+void MetricsLogSerializer::DeserializeLogs(
+ MetricsLogManager::LogType log_type,
+ std::vector<MetricsLogManager::SerializedLog>* 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);
+ if (ReadLogsFromPrefList(*unsent_logs_xml, true, logs) == RECALL_SUCCESS) {
+ // In order to try to keep the data sent to both servers roughly in sync,
+ // only read the protobuf data if we read the XML data successfully.
+ ReadLogsFromPrefList(*unsent_logs_proto, false, logs);
+ }
}
// static
void MetricsLogSerializer::WriteLogsToPrefList(
- const std::vector<std::string>& local_list,
- const size_t kMaxLocalListSize,
- ListValue* list) {
+ const std::vector<MetricsLogManager::SerializedLog>& local_list,
+ bool is_xml,
+ size_t max_list_size,
+ base::ListValue* list) {
list->Clear();
size_t start = 0;
- if (local_list.size() > kMaxLocalListSize)
- start = local_list.size() - kMaxLocalListSize;
- DCHECK(start <= local_list.size());
+ if (local_list.size() > max_list_size)
+ start = local_list.size() - max_list_size;
+ DCHECK_LE(start, local_list.size());
if (local_list.size() <= start)
return;
@@ -116,11 +147,13 @@ void MetricsLogSerializer::WriteLogsToPrefList(
base::MD5Context ctx;
base::MD5Init(&ctx);
std::string encoded_log;
- for (std::vector<std::string>::const_iterator it = local_list.begin() + start;
+ for (std::vector<MetricsLogManager::SerializedLog>::const_iterator it =
+ local_list.begin() + start;
it != local_list.end(); ++it) {
+ const std::string& value = is_xml ? it->xml : it->proto;
// We encode the compressed log as Value::CreateStringValue() expects to
// take a valid UTF8 string.
- if (!base::Base64Encode(*it, &encoded_log)) {
+ if (!base::Base64Encode(value, &encoded_log)) {
MakeStoreStatusHistogram(ENCODE_FAIL);
list->Clear();
return;
@@ -140,44 +173,58 @@ void MetricsLogSerializer::WriteLogsToPrefList(
// static
MetricsLogSerializer::LogReadStatus MetricsLogSerializer::ReadLogsFromPrefList(
const ListValue& list,
- std::vector<std::string>* local_list) {
- DCHECK(local_list->empty());
+ bool is_xml,
+ std::vector<MetricsLogManager::SerializedLog>* local_list) {
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);
+ }
+
+ // Allocate strings for all of the logs we are going to read in.
+ // Do this ahead of time so that we can decode the string values directly into
+ // the elements of |local_list|, and thereby avoid making copies of the
+ // serialized logs, which can be fairly large.
+ if (is_xml) {
+ DCHECK(local_list->empty());
+ local_list->resize(size);
+ } else if (local_list->size() != static_cast<size_t>(size)) {
+ return MakeRecallStatusHistogram(XML_PROTO_MISMATCH, false);
}
base::MD5Context ctx;
base::MD5Init(&ctx);
std::string encoded_log;
- std::string decoded_log;
+ size_t local_index = 0;
for (ListValue::const_iterator it = list.begin() + 1;
- it != list.end() - 1; ++it) { // Last element is the checksum.
- valid = (*it)->GetAsString(&encoded_log);
+ it != list.end() - 1; // Last element is the checksum.
+ ++it, ++local_index) {
+ bool 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);
+ DCHECK_LT(local_index, local_list->size());
+ std::string& decoded_log = is_xml ?
+ (*local_list)[local_index].xml :
+ (*local_list)[local_index].proto;
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);
}
// Verify checksum.
@@ -188,11 +235,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);
}
« no previous file with comments | « chrome/browser/metrics/metrics_log_serializer.h ('k') | chrome/browser/metrics/metrics_log_serializer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698