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

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: Casts for win64 compile 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
« no previous file with comments | « chrome/browser/metrics/metrics_service.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
198 #include "components/metrics/metrics_log_uploader.h"
199 #include "components/metrics/metrics_pref_names.h" 199 #include "components/metrics/metrics_pref_names.h"
200 #include "components/metrics/metrics_reporting_scheduler.h" 200 #include "components/metrics/metrics_reporting_scheduler.h"
201 #include "components/metrics/metrics_service_client.h" 201 #include "components/metrics/metrics_service_client.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_WIN) 209 #if defined(OS_WIN)
212 #include "chrome/browser/metrics/google_update_metrics_provider_win.h" 210 #include "chrome/browser/metrics/google_update_metrics_provider_win.h"
213 #endif 211 #endif
214 212
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 enum ResponseStatus { 261 enum ResponseStatus {
264 UNKNOWN_FAILURE, 262 UNKNOWN_FAILURE,
265 SUCCESS, 263 SUCCESS,
266 BAD_REQUEST, // Invalid syntax or log too large. 264 BAD_REQUEST, // Invalid syntax or log too large.
267 NO_RESPONSE, 265 NO_RESPONSE,
268 NUM_RESPONSE_STATUSES 266 NUM_RESPONSE_STATUSES
269 }; 267 };
270 268
271 ResponseStatus ResponseCodeToStatus(int response_code) { 269 ResponseStatus ResponseCodeToStatus(int response_code) {
272 switch (response_code) { 270 switch (response_code) {
271 case -1:
272 return NO_RESPONSE;
273 case 200: 273 case 200:
274 return SUCCESS; 274 return SUCCESS;
275 case 400: 275 case 400:
276 return BAD_REQUEST; 276 return BAD_REQUEST;
277 case net::URLFetcher::RESPONSE_CODE_INVALID:
278 return NO_RESPONSE;
279 default: 277 default:
280 return UNKNOWN_FAILURE; 278 return UNKNOWN_FAILURE;
281 } 279 }
282 } 280 }
283 281
284 void MarkAppCleanShutdownAndCommit(PrefService* local_state) { 282 void MarkAppCleanShutdownAndCommit(PrefService* local_state) {
285 local_state->SetBoolean(prefs::kStabilityExitedCleanly, true); 283 local_state->SetBoolean(prefs::kStabilityExitedCleanly, true);
286 local_state->SetInteger(prefs::kStabilityExecutionPhase, 284 local_state->SetInteger(prefs::kStabilityExecutionPhase,
287 MetricsService::SHUTDOWN_COMPLETE); 285 MetricsService::SHUTDOWN_COMPLETE);
288 // Start writing right away (write happens on a different thread). 286 // Start writing right away (write happens on a different thread).
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 : log_manager_(local_state, kUploadLogAvoidRetransmitSize), 362 : log_manager_(local_state, kUploadLogAvoidRetransmitSize),
365 histogram_snapshot_manager_(this), 363 histogram_snapshot_manager_(this),
366 state_manager_(state_manager), 364 state_manager_(state_manager),
367 client_(client), 365 client_(client),
368 local_state_(local_state), 366 local_state_(local_state),
369 recording_active_(false), 367 recording_active_(false),
370 reporting_active_(false), 368 reporting_active_(false),
371 test_mode_active_(false), 369 test_mode_active_(false),
372 state_(INITIALIZED), 370 state_(INITIALIZED),
373 has_initial_stability_log_(false), 371 has_initial_stability_log_(false),
372 log_upload_in_progress_(false),
374 idle_since_last_transmission_(false), 373 idle_since_last_transmission_(false),
375 session_id_(-1), 374 session_id_(-1),
376 self_ptr_factory_(this), 375 self_ptr_factory_(this),
377 state_saver_factory_(this), 376 state_saver_factory_(this) {
378 waiting_for_asynchronous_reporting_step_(false) {
379 DCHECK(IsSingleThreaded()); 377 DCHECK(IsSingleThreaded());
380 DCHECK(state_manager_); 378 DCHECK(state_manager_);
381 DCHECK(client_); 379 DCHECK(client_);
382 DCHECK(local_state_); 380 DCHECK(local_state_);
383 381
384 #if defined(OS_ANDROID) 382 #if defined(OS_ANDROID)
385 // TODO(asvitkine): Move this out of MetricsService. 383 // TODO(asvitkine): Move this out of MetricsService.
386 RegisterMetricsProvider( 384 RegisterMetricsProvider(
387 scoped_ptr<metrics::MetricsProvider>(new AndroidMetricsProvider( 385 scoped_ptr<metrics::MetricsProvider>(new AndroidMetricsProvider(
388 local_state_))); 386 local_state_)));
(...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after
878 log_manager_.FinishCurrentLog(); 876 log_manager_.FinishCurrentLog();
879 } 877 }
880 878
881 void MetricsService::PushPendingLogsToPersistentStorage() { 879 void MetricsService::PushPendingLogsToPersistentStorage() {
882 if (state_ < SENDING_INITIAL_STABILITY_LOG) 880 if (state_ < SENDING_INITIAL_STABILITY_LOG)
883 return; // We didn't and still don't have time to get plugin list etc. 881 return; // We didn't and still don't have time to get plugin list etc.
884 882
885 if (log_manager_.has_staged_log()) { 883 if (log_manager_.has_staged_log()) {
886 // We may race here, and send second copy of the log later. 884 // We may race here, and send second copy of the log later.
887 metrics::PersistedLogs::StoreType store_type; 885 metrics::PersistedLogs::StoreType store_type;
888 if (current_fetch_.get()) 886 if (log_upload_in_progress_)
889 store_type = metrics::PersistedLogs::PROVISIONAL_STORE; 887 store_type = metrics::PersistedLogs::PROVISIONAL_STORE;
890 else 888 else
891 store_type = metrics::PersistedLogs::NORMAL_STORE; 889 store_type = metrics::PersistedLogs::NORMAL_STORE;
892 log_manager_.StoreStagedLogAsUnsent(store_type); 890 log_manager_.StoreStagedLogAsUnsent(store_type);
893 } 891 }
894 DCHECK(!log_manager_.has_staged_log()); 892 DCHECK(!log_manager_.has_staged_log());
895 CloseCurrentLog(); 893 CloseCurrentLog();
896 log_manager_.PersistUnsentLogs(); 894 log_manager_.PersistUnsentLogs();
897 895
898 // If there was a staged and/or current log, then there is now at least one 896 // If there was a staged and/or current log, then there is now at least one
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
953 log_manager_.StageNextLogForUpload(); 951 log_manager_.StageNextLogForUpload();
954 SendStagedLog(); 952 SendStagedLog();
955 } else { 953 } else {
956 client_->CollectFinalMetrics( 954 client_->CollectFinalMetrics(
957 base::Bind(&MetricsService::OnFinalLogInfoCollectionDone, 955 base::Bind(&MetricsService::OnFinalLogInfoCollectionDone,
958 self_ptr_factory_.GetWeakPtr())); 956 self_ptr_factory_.GetWeakPtr()));
959 } 957 }
960 } 958 }
961 959
962 void MetricsService::OnFinalLogInfoCollectionDone() { 960 void MetricsService::OnFinalLogInfoCollectionDone() {
963 // If somehow there is a fetch in progress, we return and hope things work 961 // If somehow there is a log upload in progress, we return and hope things
964 // out. The scheduler isn't informed since if this happens, the scheduler 962 // work out. The scheduler isn't informed since if this happens, the scheduler
965 // will get a response from the upload. 963 // will get a response from the upload.
966 DCHECK(!current_fetch_.get()); 964 DCHECK(!log_upload_in_progress_);
967 if (current_fetch_.get()) 965 if (log_upload_in_progress_)
968 return; 966 return;
969 967
970 // Abort if metrics were turned off during the final info gathering. 968 // Abort if metrics were turned off during the final info gathering.
971 if (!recording_active()) { 969 if (!recording_active()) {
972 scheduler_->Stop(); 970 scheduler_->Stop();
973 scheduler_->UploadCancelled(); 971 scheduler_->UploadCancelled();
974 return; 972 return;
975 } 973 }
976 974
977 StageNewLog(); 975 StageNewLog();
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1104 1102
1105 log_manager_.FinishCurrentLog(); 1103 log_manager_.FinishCurrentLog();
1106 log_manager_.ResumePausedLog(); 1104 log_manager_.ResumePausedLog();
1107 1105
1108 DCHECK(!log_manager_.has_staged_log()); 1106 DCHECK(!log_manager_.has_staged_log());
1109 log_manager_.StageNextLogForUpload(); 1107 log_manager_.StageNextLogForUpload();
1110 } 1108 }
1111 1109
1112 void MetricsService::SendStagedLog() { 1110 void MetricsService::SendStagedLog() {
1113 DCHECK(log_manager_.has_staged_log()); 1111 DCHECK(log_manager_.has_staged_log());
1112 if (!log_manager_.has_staged_log())
1113 return;
1114 1114
1115 PrepareFetchWithStagedLog(); 1115 DCHECK(!log_upload_in_progress_);
1116 log_upload_in_progress_ = true;
1116 1117
1117 bool upload_created = (current_fetch_.get() != NULL); 1118 if (!log_uploader_) {
1118 UMA_HISTOGRAM_BOOLEAN("UMA.UploadCreation", upload_created); 1119 log_uploader_ = client_->CreateUploader(
1119 if (!upload_created) { 1120 kServerUrl, kMimeType,
1120 // Compression failed, and log discarded :-/. 1121 base::Bind(&MetricsService::OnLogUploadComplete,
1122 self_ptr_factory_.GetWeakPtr()));
1123 }
1124
1125 const std::string hash =
1126 base::HexEncode(log_manager_.staged_log_hash().data(),
1127 log_manager_.staged_log_hash().size());
1128 bool success = log_uploader_->UploadLog(log_manager_.staged_log(), hash);
1129 UMA_HISTOGRAM_BOOLEAN("UMA.UploadCreation", success);
1130 if (!success) {
1121 // Skip this upload and hope things work out next time. 1131 // Skip this upload and hope things work out next time.
1122 log_manager_.DiscardStagedLog(); 1132 log_manager_.DiscardStagedLog();
1123 scheduler_->UploadCancelled(); 1133 scheduler_->UploadCancelled();
1134 log_upload_in_progress_ = false;
1124 return; 1135 return;
1125 } 1136 }
1126 1137
1127 DCHECK(!waiting_for_asynchronous_reporting_step_);
1128 waiting_for_asynchronous_reporting_step_ = true;
1129
1130 current_fetch_->Start();
1131
1132 HandleIdleSinceLastTransmission(true); 1138 HandleIdleSinceLastTransmission(true);
1133 } 1139 }
1134 1140
1135 void MetricsService::PrepareFetchWithStagedLog() {
1136 DCHECK(log_manager_.has_staged_log());
1137 1141
1138 // Prepare the protobuf version. 1142 void MetricsService::OnLogUploadComplete(int response_code) {
1139 DCHECK(!current_fetch_.get()); 1143 DCHECK(log_upload_in_progress_);
1140 if (log_manager_.has_staged_log()) { 1144 log_upload_in_progress_ = false;
1141 current_fetch_.reset(net::URLFetcher::Create(
1142 GURL(kServerUrl), net::URLFetcher::POST, this));
1143 current_fetch_->SetRequestContext(
1144 g_browser_process->system_request_context());
1145
1146 std::string log_text = log_manager_.staged_log();
1147 std::string compressed_log_text;
1148 bool compression_successful = chrome::GzipCompress(log_text,
1149 &compressed_log_text);
1150 DCHECK(compression_successful);
1151 if (compression_successful) {
1152 current_fetch_->SetUploadData(kMimeType, compressed_log_text);
1153 // Tell the server that we're uploading gzipped protobufs.
1154 current_fetch_->SetExtraRequestHeaders("content-encoding: gzip");
1155 const std::string hash =
1156 base::HexEncode(log_manager_.staged_log_hash().data(),
1157 log_manager_.staged_log_hash().size());
1158 DCHECK(!hash.empty());
1159 current_fetch_->AddExtraRequestHeader("X-Chrome-UMA-Log-SHA1: " + hash);
1160 UMA_HISTOGRAM_PERCENTAGE(
1161 "UMA.ProtoCompressionRatio",
1162 100 * compressed_log_text.size() / log_text.size());
1163 UMA_HISTOGRAM_CUSTOM_COUNTS(
1164 "UMA.ProtoGzippedKBSaved",
1165 (log_text.size() - compressed_log_text.size()) / 1024,
1166 1, 2000, 50);
1167 }
1168
1169 // We already drop cookies server-side, but we might as well strip them out
1170 // client-side as well.
1171 current_fetch_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
1172 net::LOAD_DO_NOT_SEND_COOKIES);
1173 }
1174 }
1175
1176 void MetricsService::OnURLFetchComplete(const net::URLFetcher* source) {
1177 DCHECK(waiting_for_asynchronous_reporting_step_);
1178
1179 // We're not allowed to re-use the existing |URLFetcher|s, so free them here.
1180 // Note however that |source| is aliased to the fetcher, so we should be
1181 // careful not to delete it too early.
1182 DCHECK_EQ(current_fetch_.get(), source);
1183 scoped_ptr<net::URLFetcher> s(current_fetch_.Pass());
1184
1185 int response_code = source->GetResponseCode();
1186 1145
1187 // Log a histogram to track response success vs. failure rates. 1146 // Log a histogram to track response success vs. failure rates.
1188 UMA_HISTOGRAM_ENUMERATION("UMA.UploadResponseStatus.Protobuf", 1147 UMA_HISTOGRAM_ENUMERATION("UMA.UploadResponseStatus.Protobuf",
1189 ResponseCodeToStatus(response_code), 1148 ResponseCodeToStatus(response_code),
1190 NUM_RESPONSE_STATUSES); 1149 NUM_RESPONSE_STATUSES);
1191 1150
1192 // If the upload was provisionally stored, drop it now that the upload is 1151 // If the upload was provisionally stored, drop it now that the upload is
1193 // known to have gone through. 1152 // known to have gone through.
1194 log_manager_.DiscardLastProvisionalStore(); 1153 log_manager_.DiscardLastProvisionalStore();
1195 1154
1196 bool upload_succeeded = response_code == 200; 1155 bool upload_succeeded = response_code == 200;
1197 1156
1198 // Provide boolean for error recovery (allow us to ignore response_code). 1157 // Provide boolean for error recovery (allow us to ignore response_code).
1199 bool discard_log = false; 1158 bool discard_log = false;
1200 const size_t log_size = log_manager_.staged_log().length(); 1159 const size_t log_size = log_manager_.staged_log().length();
1201 if (!upload_succeeded && log_size > kUploadLogAvoidRetransmitSize) { 1160 if (!upload_succeeded && log_size > kUploadLogAvoidRetransmitSize) {
1202 UMA_HISTOGRAM_COUNTS("UMA.Large Rejected Log was Discarded", 1161 UMA_HISTOGRAM_COUNTS("UMA.Large Rejected Log was Discarded",
1203 static_cast<int>(log_size)); 1162 static_cast<int>(log_size));
1204 discard_log = true; 1163 discard_log = true;
1205 } else if (response_code == 400) { 1164 } else if (response_code == 400) {
1206 // Bad syntax. Retransmission won't work. 1165 // Bad syntax. Retransmission won't work.
1207 discard_log = true; 1166 discard_log = true;
1208 } 1167 }
1209 1168
1210 if (upload_succeeded || discard_log) 1169 if (upload_succeeded || discard_log)
1211 log_manager_.DiscardStagedLog(); 1170 log_manager_.DiscardStagedLog();
1212 1171
1213 waiting_for_asynchronous_reporting_step_ = false;
1214
1215 if (!log_manager_.has_staged_log()) { 1172 if (!log_manager_.has_staged_log()) {
1216 switch (state_) { 1173 switch (state_) {
1217 case SENDING_INITIAL_STABILITY_LOG: 1174 case SENDING_INITIAL_STABILITY_LOG:
1218 // Store the updated list to disk now that the removed log is uploaded. 1175 // Store the updated list to disk now that the removed log is uploaded.
1219 log_manager_.PersistUnsentLogs(); 1176 log_manager_.PersistUnsentLogs();
1220 PrepareInitialMetricsLog(); 1177 PrepareInitialMetricsLog();
1221 SendStagedLog(); 1178 SendStagedLog();
1222 state_ = SENDING_INITIAL_METRICS_LOG; 1179 state_ = SENDING_INITIAL_METRICS_LOG;
1223 break; 1180 break;
1224 1181
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
1374 RecordCurrentState(local_state_); 1331 RecordCurrentState(local_state_);
1375 } 1332 }
1376 1333
1377 void MetricsService::RecordCurrentState(PrefService* pref) { 1334 void MetricsService::RecordCurrentState(PrefService* pref) {
1378 pref->SetInt64(prefs::kStabilityLastTimestampSec, Time::Now().ToTimeT()); 1335 pref->SetInt64(prefs::kStabilityLastTimestampSec, Time::Now().ToTimeT());
1379 1336
1380 #if defined(ENABLE_PLUGINS) 1337 #if defined(ENABLE_PLUGINS)
1381 plugin_metrics_provider_->RecordPluginChanges(); 1338 plugin_metrics_provider_->RecordPluginChanges();
1382 #endif 1339 #endif
1383 } 1340 }
OLDNEW
« no previous file with comments | « chrome/browser/metrics/metrics_service.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698