OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |