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

Side by Side Diff: chrome/browser/metrics/metrics_service.cc

Issue 291153013: Make MetricsService upload logs through an interface. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 6 years, 6 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 //------------------------------------------------------------------------------ 5 //------------------------------------------------------------------------------
6 // Description of the life cycle of a instance of MetricsService. 6 // Description of the life cycle of a instance of MetricsService.
7 // 7 //
8 // OVERVIEW 8 // OVERVIEW
9 // 9 //
10 // A MetricsService instance is typically created at application startup. It is 10 // A MetricsService instance is typically created at application startup. It is
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 #include "base/strings/utf_string_conversions.h" 178 #include "base/strings/utf_string_conversions.h"
179 #include "base/threading/platform_thread.h" 179 #include "base/threading/platform_thread.h"
180 #include "base/threading/thread.h" 180 #include "base/threading/thread.h"
181 #include "base/threading/thread_restrictions.h" 181 #include "base/threading/thread_restrictions.h"
182 #include "base/tracked_objects.h" 182 #include "base/tracked_objects.h"
183 #include "base/values.h" 183 #include "base/values.h"
184 #include "chrome/browser/browser_process.h" 184 #include "chrome/browser/browser_process.h"
185 #include "chrome/browser/chrome_notification_types.h" 185 #include "chrome/browser/chrome_notification_types.h"
186 #include "chrome/browser/io_thread.h" 186 #include "chrome/browser/io_thread.h"
187 #include "chrome/browser/metrics/chrome_stability_metrics_provider.h" 187 #include "chrome/browser/metrics/chrome_stability_metrics_provider.h"
188 #include "chrome/browser/metrics/compression_utils.h"
189 #include "chrome/browser/metrics/gpu_metrics_provider.h" 188 #include "chrome/browser/metrics/gpu_metrics_provider.h"
190 #include "chrome/browser/metrics/metrics_log.h" 189 #include "chrome/browser/metrics/metrics_log.h"
191 #include "chrome/browser/metrics/metrics_state_manager.h" 190 #include "chrome/browser/metrics/metrics_state_manager.h"
192 #include "chrome/browser/metrics/network_metrics_provider.h" 191 #include "chrome/browser/metrics/network_metrics_provider.h"
193 #include "chrome/browser/metrics/omnibox_metrics_provider.h" 192 #include "chrome/browser/metrics/omnibox_metrics_provider.h"
194 #include "chrome/browser/metrics/tracking_synchronizer.h" 193 #include "chrome/browser/metrics/tracking_synchronizer.h"
195 #include "chrome/common/pref_names.h" 194 #include "chrome/common/pref_names.h"
196 #include "chrome/common/variations/variations_util.h" 195 #include "chrome/common/variations/variations_util.h"
197 #include "components/metrics/metrics_log_base.h" 196 #include "components/metrics/metrics_log_base.h"
198 #include "components/metrics/metrics_log_manager.h" 197 #include "components/metrics/metrics_log_manager.h"
199 #include "components/metrics/metrics_pref_names.h" 198 #include "components/metrics/metrics_pref_names.h"
200 #include "components/metrics/metrics_reporting_scheduler.h" 199 #include "components/metrics/metrics_reporting_scheduler.h"
201 #include "components/metrics/metrics_service_client.h" 200 #include "components/metrics/metrics_service_client.h"
201 #include "components/metrics/net/compression_utils.h"
202 #include "components/variations/entropy_provider.h" 202 #include "components/variations/entropy_provider.h"
203 #include "net/base/load_flags.h"
204 #include "net/url_request/url_fetcher.h"
205 203
206 #if defined(ENABLE_PLUGINS) 204 #if defined(ENABLE_PLUGINS)
207 // TODO(asvitkine): Move this out of MetricsService. 205 // TODO(asvitkine): Move this out of MetricsService.
208 #include "chrome/browser/metrics/plugin_metrics_provider.h" 206 #include "chrome/browser/metrics/plugin_metrics_provider.h"
209 #endif 207 #endif
210 208
211 #if defined(OS_CHROMEOS) 209 #if defined(OS_CHROMEOS)
212 #include "chrome/browser/chromeos/settings/cros_settings.h" 210 #include "chrome/browser/chromeos/settings/cros_settings.h"
213 #include "chrome/browser/metrics/chromeos_metrics_provider.h" 211 #include "chrome/browser/metrics/chromeos_metrics_provider.h"
214 #include "chromeos/system/statistics_provider.h" 212 #include "chromeos/system/statistics_provider.h"
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 enum ResponseStatus { 268 enum ResponseStatus {
271 UNKNOWN_FAILURE, 269 UNKNOWN_FAILURE,
272 SUCCESS, 270 SUCCESS,
273 BAD_REQUEST, // Invalid syntax or log too large. 271 BAD_REQUEST, // Invalid syntax or log too large.
274 NO_RESPONSE, 272 NO_RESPONSE,
275 NUM_RESPONSE_STATUSES 273 NUM_RESPONSE_STATUSES
276 }; 274 };
277 275
278 ResponseStatus ResponseCodeToStatus(int response_code) { 276 ResponseStatus ResponseCodeToStatus(int response_code) {
279 switch (response_code) { 277 switch (response_code) {
278 case -1:
279 return NO_RESPONSE;
280 case 200: 280 case 200:
281 return SUCCESS; 281 return SUCCESS;
282 case 400: 282 case 400:
283 return BAD_REQUEST; 283 return BAD_REQUEST;
284 case net::URLFetcher::RESPONSE_CODE_INVALID:
285 return NO_RESPONSE;
286 default: 284 default:
287 return UNKNOWN_FAILURE; 285 return UNKNOWN_FAILURE;
288 } 286 }
289 } 287 }
290 288
291 void MarkAppCleanShutdownAndCommit() { 289 void MarkAppCleanShutdownAndCommit() {
292 PrefService* pref = g_browser_process->local_state(); 290 PrefService* pref = g_browser_process->local_state();
293 pref->SetBoolean(prefs::kStabilityExitedCleanly, true); 291 pref->SetBoolean(prefs::kStabilityExitedCleanly, true);
294 pref->SetInteger(prefs::kStabilityExecutionPhase, 292 pref->SetInteger(prefs::kStabilityExecutionPhase,
295 MetricsService::SHUTDOWN_COMPLETE); 293 MetricsService::SHUTDOWN_COMPLETE);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 : log_manager_(g_browser_process->local_state(), 369 : log_manager_(g_browser_process->local_state(),
372 kUploadLogAvoidRetransmitSize), 370 kUploadLogAvoidRetransmitSize),
373 histogram_snapshot_manager_(this), 371 histogram_snapshot_manager_(this),
374 state_manager_(state_manager), 372 state_manager_(state_manager),
375 client_(client), 373 client_(client),
376 recording_active_(false), 374 recording_active_(false),
377 reporting_active_(false), 375 reporting_active_(false),
378 test_mode_active_(false), 376 test_mode_active_(false),
379 state_(INITIALIZED), 377 state_(INITIALIZED),
380 has_initial_stability_log_(false), 378 has_initial_stability_log_(false),
379 log_upload_in_progress_(false),
381 idle_since_last_transmission_(false), 380 idle_since_last_transmission_(false),
382 session_id_(-1), 381 session_id_(-1),
383 next_window_id_(0), 382 next_window_id_(0),
384 self_ptr_factory_(this), 383 self_ptr_factory_(this),
385 state_saver_factory_(this), 384 state_saver_factory_(this) {
386 waiting_for_asynchronous_reporting_step_(false) {
387 DCHECK(IsSingleThreaded()); 385 DCHECK(IsSingleThreaded());
388 DCHECK(state_manager_); 386 DCHECK(state_manager_);
389 DCHECK(client_); 387 DCHECK(client_);
390 388
391 #if defined(OS_ANDROID) 389 #if defined(OS_ANDROID)
392 // TODO(asvitkine): Move this out of MetricsService. 390 // TODO(asvitkine): Move this out of MetricsService.
393 RegisterMetricsProvider( 391 RegisterMetricsProvider(
394 scoped_ptr<metrics::MetricsProvider>(new AndroidMetricsProvider( 392 scoped_ptr<metrics::MetricsProvider>(new AndroidMetricsProvider(
395 g_browser_process->local_state()))); 393 g_browser_process->local_state())));
396 #endif // defined(OS_ANDROID) 394 #endif // defined(OS_ANDROID)
(...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after
924 log_manager_.FinishCurrentLog(); 922 log_manager_.FinishCurrentLog();
925 } 923 }
926 924
927 void MetricsService::PushPendingLogsToPersistentStorage() { 925 void MetricsService::PushPendingLogsToPersistentStorage() {
928 if (state_ < SENDING_INITIAL_STABILITY_LOG) 926 if (state_ < SENDING_INITIAL_STABILITY_LOG)
929 return; // We didn't and still don't have time to get plugin list etc. 927 return; // We didn't and still don't have time to get plugin list etc.
930 928
931 if (log_manager_.has_staged_log()) { 929 if (log_manager_.has_staged_log()) {
932 // We may race here, and send second copy of the log later. 930 // We may race here, and send second copy of the log later.
933 metrics::PersistedLogs::StoreType store_type; 931 metrics::PersistedLogs::StoreType store_type;
934 if (current_fetch_.get()) 932 if (log_upload_in_progress_)
935 store_type = metrics::PersistedLogs::PROVISIONAL_STORE; 933 store_type = metrics::PersistedLogs::PROVISIONAL_STORE;
936 else 934 else
937 store_type = metrics::PersistedLogs::NORMAL_STORE; 935 store_type = metrics::PersistedLogs::NORMAL_STORE;
938 log_manager_.StoreStagedLogAsUnsent(store_type); 936 log_manager_.StoreStagedLogAsUnsent(store_type);
939 } 937 }
940 DCHECK(!log_manager_.has_staged_log()); 938 DCHECK(!log_manager_.has_staged_log());
941 CloseCurrentLog(); 939 CloseCurrentLog();
942 log_manager_.PersistUnsentLogs(); 940 log_manager_.PersistUnsentLogs();
943 941
944 // If there was a staged and/or current log, then there is now at least one 942 // If there was a staged and/or current log, then there is now at least one
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1002 client_->CollectFinalMetrics( 1000 client_->CollectFinalMetrics(
1003 base::Bind(&MetricsService::OnFinalLogInfoCollectionDone, 1001 base::Bind(&MetricsService::OnFinalLogInfoCollectionDone,
1004 self_ptr_factory_.GetWeakPtr())); 1002 self_ptr_factory_.GetWeakPtr()));
1005 } 1003 }
1006 } 1004 }
1007 1005
1008 void MetricsService::OnFinalLogInfoCollectionDone() { 1006 void MetricsService::OnFinalLogInfoCollectionDone() {
1009 // If somehow there is a fetch in progress, we return and hope things work 1007 // If somehow there is a fetch in progress, we return and hope things work
1010 // out. The scheduler isn't informed since if this happens, the scheduler 1008 // out. The scheduler isn't informed since if this happens, the scheduler
1011 // will get a response from the upload. 1009 // will get a response from the upload.
1012 DCHECK(!current_fetch_.get()); 1010 DCHECK(!log_upload_in_progress_);
1013 if (current_fetch_.get()) 1011 if (log_upload_in_progress_)
1014 return; 1012 return;
1015 1013
1016 // Abort if metrics were turned off during the final info gathering. 1014 // Abort if metrics were turned off during the final info gathering.
1017 if (!recording_active()) { 1015 if (!recording_active()) {
1018 scheduler_->Stop(); 1016 scheduler_->Stop();
1019 scheduler_->UploadCancelled(); 1017 scheduler_->UploadCancelled();
1020 return; 1018 return;
1021 } 1019 }
1022 1020
1023 StageNewLog(); 1021 StageNewLog();
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
1153 1151
1154 log_manager_.FinishCurrentLog(); 1152 log_manager_.FinishCurrentLog();
1155 log_manager_.ResumePausedLog(); 1153 log_manager_.ResumePausedLog();
1156 1154
1157 DCHECK(!log_manager_.has_staged_log()); 1155 DCHECK(!log_manager_.has_staged_log());
1158 log_manager_.StageNextLogForUpload(); 1156 log_manager_.StageNextLogForUpload();
1159 } 1157 }
1160 1158
1161 void MetricsService::SendStagedLog() { 1159 void MetricsService::SendStagedLog() {
1162 DCHECK(log_manager_.has_staged_log()); 1160 DCHECK(log_manager_.has_staged_log());
1161 if (!log_manager_.has_staged_log())
1162 return;
1163 1163
1164 PrepareFetchWithStagedLog(); 1164 DCHECK(!log_upload_in_progress_);
1165 log_upload_in_progress_ = true;
1165 1166
1166 bool upload_created = (current_fetch_.get() != NULL); 1167 if (!log_uploader_) {
1167 UMA_HISTOGRAM_BOOLEAN("UMA.UploadCreation", upload_created); 1168 log_uploader_ = client_->CreateUploader(
1168 if (!upload_created) { 1169 kServerUrl, kMimeType,
1170 base::Bind(&MetricsService::OnLogUploadComplete,
1171 self_ptr_factory_.GetWeakPtr()));
1172 }
1173
1174 const std::string hash =
1175 base::HexEncode(log_manager_.staged_log_hash().data(),
1176 log_manager_.staged_log_hash().size());
1177 bool success = log_uploader_->UploadLog(log_manager_.staged_log(), hash);
1178 UMA_HISTOGRAM_BOOLEAN("UMA.UploadCreation", success);
1179 if (!success) {
1169 // Compression failed, and log discarded :-/. 1180 // Compression failed, and log discarded :-/.
blundell 2014/05/26 07:56:56 is this comment a little out of date now?
Alexei Svitkine (slow) 2014/05/26 20:04:10 Done.
1170 // Skip this upload and hope things work out next time. 1181 // Skip this upload and hope things work out next time.
1171 log_manager_.DiscardStagedLog(); 1182 log_manager_.DiscardStagedLog();
1172 scheduler_->UploadCancelled(); 1183 scheduler_->UploadCancelled();
1173 return; 1184 return;
1174 } 1185 }
1175 1186
1176 DCHECK(!waiting_for_asynchronous_reporting_step_);
1177 waiting_for_asynchronous_reporting_step_ = true;
1178
1179 current_fetch_->Start();
1180
1181 HandleIdleSinceLastTransmission(true); 1187 HandleIdleSinceLastTransmission(true);
1182 } 1188 }
1183 1189
1184 void MetricsService::PrepareFetchWithStagedLog() {
1185 DCHECK(log_manager_.has_staged_log());
1186 1190
1187 // Prepare the protobuf version. 1191 void MetricsService::OnLogUploadComplete(int response_code) {
1188 DCHECK(!current_fetch_.get()); 1192 DCHECK(log_upload_in_progress_);
1189 if (log_manager_.has_staged_log()) { 1193 log_upload_in_progress_ = false;
1190 current_fetch_.reset(net::URLFetcher::Create(
1191 GURL(kServerUrl), net::URLFetcher::POST, this));
1192 current_fetch_->SetRequestContext(
1193 g_browser_process->system_request_context());
1194
1195 std::string log_text = log_manager_.staged_log();
1196 std::string compressed_log_text;
1197 bool compression_successful = chrome::GzipCompress(log_text,
1198 &compressed_log_text);
1199 DCHECK(compression_successful);
1200 if (compression_successful) {
1201 current_fetch_->SetUploadData(kMimeType, compressed_log_text);
1202 // Tell the server that we're uploading gzipped protobufs.
1203 current_fetch_->SetExtraRequestHeaders("content-encoding: gzip");
1204 const std::string hash =
1205 base::HexEncode(log_manager_.staged_log_hash().data(),
1206 log_manager_.staged_log_hash().size());
1207 DCHECK(!hash.empty());
1208 current_fetch_->AddExtraRequestHeader("X-Chrome-UMA-Log-SHA1: " + hash);
1209 UMA_HISTOGRAM_PERCENTAGE(
1210 "UMA.ProtoCompressionRatio",
1211 100 * compressed_log_text.size() / log_text.size());
1212 UMA_HISTOGRAM_CUSTOM_COUNTS(
1213 "UMA.ProtoGzippedKBSaved",
1214 (log_text.size() - compressed_log_text.size()) / 1024,
1215 1, 2000, 50);
1216 }
1217
1218 // We already drop cookies server-side, but we might as well strip them out
1219 // client-side as well.
1220 current_fetch_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
1221 net::LOAD_DO_NOT_SEND_COOKIES);
1222 }
1223 }
1224
1225 void MetricsService::OnURLFetchComplete(const net::URLFetcher* source) {
1226 DCHECK(waiting_for_asynchronous_reporting_step_);
1227
1228 // We're not allowed to re-use the existing |URLFetcher|s, so free them here.
1229 // Note however that |source| is aliased to the fetcher, so we should be
1230 // careful not to delete it too early.
1231 DCHECK_EQ(current_fetch_.get(), source);
1232 scoped_ptr<net::URLFetcher> s(current_fetch_.Pass());
1233
1234 int response_code = source->GetResponseCode();
1235 1194
1236 // Log a histogram to track response success vs. failure rates. 1195 // Log a histogram to track response success vs. failure rates.
1237 UMA_HISTOGRAM_ENUMERATION("UMA.UploadResponseStatus.Protobuf", 1196 UMA_HISTOGRAM_ENUMERATION("UMA.UploadResponseStatus.Protobuf",
1238 ResponseCodeToStatus(response_code), 1197 ResponseCodeToStatus(response_code),
1239 NUM_RESPONSE_STATUSES); 1198 NUM_RESPONSE_STATUSES);
1240 1199
1241 // If the upload was provisionally stored, drop it now that the upload is 1200 // If the upload was provisionally stored, drop it now that the upload is
1242 // known to have gone through. 1201 // known to have gone through.
1243 log_manager_.DiscardLastProvisionalStore(); 1202 log_manager_.DiscardLastProvisionalStore();
1244 1203
1245 bool upload_succeeded = response_code == 200; 1204 bool upload_succeeded = response_code == 200;
1246 1205
1247 // Provide boolean for error recovery (allow us to ignore response_code). 1206 // Provide boolean for error recovery (allow us to ignore response_code).
1248 bool discard_log = false; 1207 bool discard_log = false;
1249 const size_t log_size = log_manager_.staged_log().length(); 1208 const size_t log_size = log_manager_.staged_log().length();
1250 if (!upload_succeeded && log_size > kUploadLogAvoidRetransmitSize) { 1209 if (!upload_succeeded && log_size > kUploadLogAvoidRetransmitSize) {
1251 UMA_HISTOGRAM_COUNTS("UMA.Large Rejected Log was Discarded", 1210 UMA_HISTOGRAM_COUNTS("UMA.Large Rejected Log was Discarded",
1252 static_cast<int>(log_size)); 1211 static_cast<int>(log_size));
1253 discard_log = true; 1212 discard_log = true;
1254 } else if (response_code == 400) { 1213 } else if (response_code == 400) {
1255 // Bad syntax. Retransmission won't work. 1214 // Bad syntax. Retransmission won't work.
1256 discard_log = true; 1215 discard_log = true;
1257 } 1216 }
1258 1217
1259 if (upload_succeeded || discard_log) 1218 if (upload_succeeded || discard_log)
1260 log_manager_.DiscardStagedLog(); 1219 log_manager_.DiscardStagedLog();
1261 1220
1262 waiting_for_asynchronous_reporting_step_ = false;
1263
1264 if (!log_manager_.has_staged_log()) { 1221 if (!log_manager_.has_staged_log()) {
1265 switch (state_) { 1222 switch (state_) {
1266 case SENDING_INITIAL_STABILITY_LOG: 1223 case SENDING_INITIAL_STABILITY_LOG:
1267 // Store the updated list to disk now that the removed log is uploaded. 1224 // Store the updated list to disk now that the removed log is uploaded.
1268 log_manager_.PersistUnsentLogs(); 1225 log_manager_.PersistUnsentLogs();
1269 PrepareInitialMetricsLog(); 1226 PrepareInitialMetricsLog();
1270 SendStagedLog(); 1227 SendStagedLog();
1271 state_ = SENDING_INITIAL_METRICS_LOG; 1228 state_ = SENDING_INITIAL_METRICS_LOG;
1272 break; 1229 break;
1273 1230
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1429 RecordCurrentState(pref); 1386 RecordCurrentState(pref);
1430 } 1387 }
1431 1388
1432 void MetricsService::RecordCurrentState(PrefService* pref) { 1389 void MetricsService::RecordCurrentState(PrefService* pref) {
1433 pref->SetInt64(prefs::kStabilityLastTimestampSec, Time::Now().ToTimeT()); 1390 pref->SetInt64(prefs::kStabilityLastTimestampSec, Time::Now().ToTimeT());
1434 1391
1435 #if defined(ENABLE_PLUGINS) 1392 #if defined(ENABLE_PLUGINS)
1436 plugin_metrics_provider_->RecordPluginChanges(); 1393 plugin_metrics_provider_->RecordPluginChanges();
1437 #endif 1394 #endif
1438 } 1395 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698