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

Side by Side Diff: chrome/common/metrics/metrics_log_manager.cc

Issue 9396001: Begin to separate the MetricsService logic for creating vs uploading logs (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address review comments Created 8 years, 9 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "chrome/common/metrics/metrics_log_manager.h" 5 #include "chrome/common/metrics/metrics_log_manager.h"
6 6
7 #if defined(USE_SYSTEM_LIBBZ2) 7 #if defined(USE_SYSTEM_LIBBZ2)
8 #include <bzlib.h> 8 #include <bzlib.h>
9 #else 9 #else
10 #include "third_party/bzip2/bzlib.h" 10 #include "third_party/bzip2/bzlib.h"
11 #endif 11 #endif
12 12
13 #include "base/metrics/histogram.h" 13 #include "base/metrics/histogram.h"
14 #include "base/string_util.h" 14 #include "base/string_util.h"
15 #include "chrome/common/metrics/metrics_log_base.h" 15 #include "chrome/common/metrics/metrics_log_base.h"
16 16
17 namespace { 17 namespace {
18 18
19 // Used to keep track of discarded protobuf logs without having to track xml and 19 // Used to keep track of discarded protobuf logs without having to track xml and
20 // protobuf logs in separate lists. 20 // protobuf logs in separate lists.
21 const char kDiscardedLog[] = "Log discarded"; 21 const char kDiscardedLog[] = "Log discarded";
22 22
23 } // anonymous namespace 23 } // anonymous namespace
24 24
25 MetricsLogManager::MetricsLogManager() : max_ongoing_log_store_size_(0) {} 25 MetricsLogManager::MetricsLogManager() : current_log_type_(INITIAL_LOG),
26 staged_log_type_(INITIAL_LOG),
27 max_ongoing_log_store_size_(0) {}
26 28
27 MetricsLogManager::~MetricsLogManager() {} 29 MetricsLogManager::~MetricsLogManager() {}
28 30
29 bool MetricsLogManager::SerializedLog::empty() const { 31 bool MetricsLogManager::SerializedLog::empty() const {
30 DCHECK_EQ(xml.empty(), proto.empty()); 32 DCHECK_EQ(xml.empty(), proto.empty());
31 return xml.empty(); 33 return xml.empty();
32 } 34 }
33 35
34 void MetricsLogManager::BeginLoggingWithLog(MetricsLogBase* log) { 36 void MetricsLogManager::SerializedLog::swap(SerializedLog& log) {
37 xml.swap(log.xml);
38 proto.swap(log.proto);
39 }
40
41 void MetricsLogManager::BeginLoggingWithLog(MetricsLogBase* log,
42 LogType log_type) {
35 DCHECK(!current_log_.get()); 43 DCHECK(!current_log_.get());
36 current_log_.reset(log); 44 current_log_.reset(log);
45 current_log_type_ = log_type;
37 } 46 }
38 47
39 void MetricsLogManager::StageCurrentLogForUpload() { 48 void MetricsLogManager::FinishCurrentLog() {
40 DCHECK(current_log_.get()); 49 DCHECK(current_log_.get());
41 current_log_->CloseLog(); 50 current_log_->CloseLog();
42 staged_log_.reset(current_log_.release()); 51 SerializedLog compressed_log;
43 CompressStagedLog(); 52 CompressCurrentLog(&compressed_log);
53 if (!compressed_log.empty())
54 StoreLog(&compressed_log, current_log_type_);
55 current_log_.reset();
56 }
57
58 void MetricsLogManager::StageNextLogForUpload() {
59 // Prioritize initial logs for uploading.
60 std::vector<SerializedLog>* source_list =
61 unsent_initial_logs_.empty() ? &unsent_ongoing_logs_
62 : &unsent_initial_logs_;
63 DCHECK(!source_list->empty());
64 DCHECK(staged_log_text_.empty());
65 staged_log_text_.swap(source_list->back());
66 source_list->pop_back();
44 } 67 }
45 68
46 bool MetricsLogManager::has_staged_log() const { 69 bool MetricsLogManager::has_staged_log() const {
47 return staged_log_.get() || !staged_log_text().empty(); 70 return !staged_log_text().empty();
48 } 71 }
49 72
50 bool MetricsLogManager::has_staged_log_proto() const { 73 bool MetricsLogManager::has_staged_log_proto() const {
51 return has_staged_log() && staged_log_text().proto != kDiscardedLog; 74 return has_staged_log() && staged_log_text().proto != kDiscardedLog;
52 } 75 }
53 76
54 void MetricsLogManager::DiscardStagedLog() { 77 void MetricsLogManager::DiscardStagedLog() {
55 staged_log_.reset();
56 staged_log_text_.xml.clear(); 78 staged_log_text_.xml.clear();
57 staged_log_text_.proto.clear(); 79 staged_log_text_.proto.clear();
58 } 80 }
59 81
60 void MetricsLogManager::DiscardStagedLogProto() { 82 void MetricsLogManager::DiscardStagedLogProto() {
61 staged_log_text_.proto = kDiscardedLog; 83 staged_log_text_.proto = kDiscardedLog;
62 } 84 }
63 85
64 void MetricsLogManager::DiscardCurrentLog() { 86 void MetricsLogManager::DiscardCurrentLog() {
65 current_log_->CloseLog(); 87 current_log_->CloseLog();
66 current_log_.reset(); 88 current_log_.reset();
67 } 89 }
68 90
69 void MetricsLogManager::PauseCurrentLog() { 91 void MetricsLogManager::PauseCurrentLog() {
70 DCHECK(!paused_log_.get()); 92 DCHECK(!paused_log_.get());
71 paused_log_.reset(current_log_.release()); 93 paused_log_.reset(current_log_.release());
72 } 94 }
73 95
74 void MetricsLogManager::ResumePausedLog() { 96 void MetricsLogManager::ResumePausedLog() {
75 DCHECK(!current_log_.get()); 97 DCHECK(!current_log_.get());
76 current_log_.reset(paused_log_.release()); 98 current_log_.reset(paused_log_.release());
77 } 99 }
78 100
79 void MetricsLogManager::StoreStagedLogAsUnsent(LogType log_type) { 101 void MetricsLogManager::StoreStagedLogAsUnsent() {
80 DCHECK(has_staged_log()); 102 DCHECK(has_staged_log());
81 103
82 // If compressing the log failed, there's nothing to store. 104 // If compressing the log failed, there's nothing to store.
83 if (staged_log_text().empty()) 105 if (staged_log_text_.empty())
84 return; 106 return;
85 107
86 if (log_type == INITIAL_LOG) { 108 StoreLog(&staged_log_text_, staged_log_type_);
87 unsent_initial_logs_.push_back(staged_log_text_);
88 } else {
89 // If it's too large, just note that and discard it.
90 if (max_ongoing_log_store_size_ &&
91 staged_log_text().xml.length() > max_ongoing_log_store_size_) {
92 // TODO(isherman): We probably want a similar check for protobufs, but we
93 // don't want to prevent XML upload just because the protobuf version is
94 // too long. In practice, I'm pretty sure the XML version should always
95 // be longer, or at least on the same order of magnitude in length.
96 UMA_HISTOGRAM_COUNTS(
97 "UMA.Large Accumulated Log Not Persisted",
98 static_cast<int>(staged_log_text().xml.length()));
99 } else {
100 unsent_ongoing_logs_.push_back(staged_log_text_);
101 }
102 }
103 DiscardStagedLog(); 109 DiscardStagedLog();
104 } 110 }
105 111
106 void MetricsLogManager::StageNextStoredLogForUpload() { 112 void MetricsLogManager::StoreLog(SerializedLog* log_text, LogType log_type) {
107 // Prioritize initial logs for uploading. 113 std::vector<SerializedLog>* destination_list =
108 std::vector<SerializedLog>* source_list = 114 (log_type == INITIAL_LOG) ? &unsent_initial_logs_
109 unsent_initial_logs_.empty() ? 115 : &unsent_ongoing_logs_;
110 &unsent_ongoing_logs_ : 116 destination_list->push_back(SerializedLog());
111 &unsent_initial_logs_; 117 destination_list->back().swap(*log_text);
112 DCHECK(!source_list->empty());
113 DCHECK(staged_log_text().empty());
114 staged_log_text_ = source_list->back();
115 source_list->pop_back();
116 } 118 }
117 119
118 void MetricsLogManager::PersistUnsentLogs() { 120 void MetricsLogManager::PersistUnsentLogs() {
119 DCHECK(log_serializer_.get()); 121 DCHECK(log_serializer_.get());
120 if (!log_serializer_.get()) 122 if (!log_serializer_.get())
121 return; 123 return;
124 // Remove any ongoing logs that are over the serialization size limit.
125 if (max_ongoing_log_store_size_) {
126 for (std::vector<SerializedLog>::iterator it = unsent_ongoing_logs_.begin();
127 it != unsent_ongoing_logs_.end();) {
128 size_t log_size = it->xml.length();
129 if (log_size > max_ongoing_log_store_size_) {
130 // TODO(isherman): We probably want a similar check for protobufs, but
131 // we don't want to prevent XML upload just because the protobuf version
132 // is too long. In practice, I'm pretty sure the XML version should
133 // always be longer, or at least on the same order of magnitude in
134 // length.
135 UMA_HISTOGRAM_COUNTS("UMA.Large Accumulated Log Not Persisted",
136 static_cast<int>(log_size));
137 it = unsent_ongoing_logs_.erase(it);
138 } else {
139 ++it;
140 }
141 }
142 }
122 log_serializer_->SerializeLogs(unsent_initial_logs_, INITIAL_LOG); 143 log_serializer_->SerializeLogs(unsent_initial_logs_, INITIAL_LOG);
123 log_serializer_->SerializeLogs(unsent_ongoing_logs_, ONGOING_LOG); 144 log_serializer_->SerializeLogs(unsent_ongoing_logs_, ONGOING_LOG);
124 } 145 }
125 146
126 void MetricsLogManager::LoadPersistedUnsentLogs() { 147 void MetricsLogManager::LoadPersistedUnsentLogs() {
127 DCHECK(log_serializer_.get()); 148 DCHECK(log_serializer_.get());
128 if (!log_serializer_.get()) 149 if (!log_serializer_.get())
129 return; 150 return;
130 log_serializer_->DeserializeLogs(INITIAL_LOG, &unsent_initial_logs_); 151 log_serializer_->DeserializeLogs(INITIAL_LOG, &unsent_initial_logs_);
131 log_serializer_->DeserializeLogs(ONGOING_LOG, &unsent_ongoing_logs_); 152 log_serializer_->DeserializeLogs(ONGOING_LOG, &unsent_ongoing_logs_);
132 } 153 }
133 154
134 void MetricsLogManager::CompressStagedLog() { 155 void MetricsLogManager::CompressCurrentLog(SerializedLog* compressed_log) {
135 int text_size = staged_log_->GetEncodedLogSizeXml(); 156 int text_size = current_log_->GetEncodedLogSizeXml();
136 std::string staged_log_text;
137 DCHECK_GT(text_size, 0); 157 DCHECK_GT(text_size, 0);
138 staged_log_->GetEncodedLogXml(WriteInto(&staged_log_text, text_size + 1), 158 std::string log_text;
139 text_size); 159 current_log_->GetEncodedLogXml(WriteInto(&log_text, text_size + 1),
160 text_size);
140 161
141 bool success = Bzip2Compress(staged_log_text, &staged_log_text_.xml); 162 bool success = Bzip2Compress(log_text, &(compressed_log->xml));
142 if (success) { 163 if (success) {
143 // Allow security-conscious users to see all metrics logs that we send. 164 // Allow security-conscious users to see all metrics logs that we send.
144 DVLOG(1) << "METRICS LOG: " << staged_log_text; 165 DVLOG(1) << "METRICS LOG: " << log_text;
145 166
146 // Note that we only save the protobuf version if we succeeded in 167 // Note that we only save the protobuf version if we succeeded in
147 // compressing the XML, so that the two data streams are the same. 168 // compressing the XML, so that the two data streams are the same.
148 staged_log_->GetEncodedLogProto(&staged_log_text_.proto); 169 current_log_->GetEncodedLogProto(&(compressed_log->proto));
149 } else { 170 } else {
150 NOTREACHED() << "Failed to compress log for transmission."; 171 NOTREACHED() << "Failed to compress log for transmission.";
151 } 172 }
152 } 173 }
153 174
154 // static 175 // static
155 // This implementation is based on the Firefox MetricsService implementation. 176 // This implementation is based on the Firefox MetricsService implementation.
156 bool MetricsLogManager::Bzip2Compress(const std::string& input, 177 bool MetricsLogManager::Bzip2Compress(const std::string& input,
157 std::string* output) { 178 std::string* output) {
158 bz_stream stream = {0}; 179 bz_stream stream = {0};
(...skipping 27 matching lines...) Expand all
186 // TODO(jar): See if it would be better to do a CHECK() here. 207 // TODO(jar): See if it would be better to do a CHECK() here.
187 return false; 208 return false;
188 } 209 }
189 result = BZ2_bzCompressEnd(&stream); 210 result = BZ2_bzCompressEnd(&stream);
190 DCHECK(result == BZ_OK); 211 DCHECK(result == BZ_OK);
191 212
192 output->resize(stream.total_out_lo32); 213 output->resize(stream.total_out_lo32);
193 214
194 return true; 215 return true;
195 } 216 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698