| 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 | 10 // A MetricsService instance is typically created at application startup. It |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 #include "chrome/common/guid.h" | 175 #include "chrome/common/guid.h" |
| 176 #include "chrome/common/metrics/metrics_log_manager.h" | 176 #include "chrome/common/metrics/metrics_log_manager.h" |
| 177 #include "chrome/common/pref_names.h" | 177 #include "chrome/common/pref_names.h" |
| 178 #include "chrome/common/render_messages.h" | 178 #include "chrome/common/render_messages.h" |
| 179 #include "content/browser/load_notification_details.h" | 179 #include "content/browser/load_notification_details.h" |
| 180 #include "content/public/browser/child_process_data.h" | 180 #include "content/public/browser/child_process_data.h" |
| 181 #include "content/public/browser/notification_service.h" | 181 #include "content/public/browser/notification_service.h" |
| 182 #include "content/public/browser/plugin_service.h" | 182 #include "content/public/browser/plugin_service.h" |
| 183 #include "content/public/browser/render_process_host.h" | 183 #include "content/public/browser/render_process_host.h" |
| 184 #include "content/public/common/url_fetcher.h" | 184 #include "content/public/common/url_fetcher.h" |
| 185 #include "net/base/load_flags.h" |
| 185 #include "webkit/plugins/webplugininfo.h" | 186 #include "webkit/plugins/webplugininfo.h" |
| 186 | 187 |
| 187 // TODO(port): port browser_distribution.h. | 188 // TODO(port): port browser_distribution.h. |
| 188 #if !defined(OS_POSIX) | 189 #if !defined(OS_POSIX) |
| 189 #include "chrome/installer/util/browser_distribution.h" | 190 #include "chrome/installer/util/browser_distribution.h" |
| 190 #endif | 191 #endif |
| 191 | 192 |
| 192 #if defined(OS_CHROMEOS) | 193 #if defined(OS_CHROMEOS) |
| 193 #include "chrome/browser/chromeos/cros/cros_library.h" | 194 #include "chrome/browser/chromeos/cros/cros_library.h" |
| 194 #include "chrome/browser/chromeos/external_metrics.h" | 195 #include "chrome/browser/chromeos/external_metrics.h" |
| 195 #include "chrome/browser/chromeos/system/statistics_provider.h" | 196 #include "chrome/browser/chromeos/system/statistics_provider.h" |
| 196 #endif | 197 #endif |
| 197 | 198 |
| 198 using base::Time; | 199 using base::Time; |
| 199 using content::BrowserThread; | 200 using content::BrowserThread; |
| 200 using content::ChildProcessData; | 201 using content::ChildProcessData; |
| 201 using content::PluginService; | 202 using content::PluginService; |
| 202 | 203 |
| 204 namespace { |
| 205 |
| 203 // Check to see that we're being called on only one thread. | 206 // Check to see that we're being called on only one thread. |
| 204 static bool IsSingleThreaded(); | 207 bool IsSingleThreaded() { |
| 208 static base::PlatformThreadId thread_id = 0; |
| 209 if (!thread_id) |
| 210 thread_id = base::PlatformThread::CurrentId(); |
| 211 return base::PlatformThread::CurrentId() == thread_id; |
| 212 } |
| 205 | 213 |
| 206 static const char kMetricsType[] = "application/vnd.mozilla.metrics.bz2"; | 214 const char kMetricsTypeXml[] = "application/vnd.mozilla.metrics.bz2"; |
| 215 const char kMetricsTypeProto[] = "application/vnd.chrome.uma"; |
| 216 |
| 217 const char kServerUrlXml[] = |
| 218 "https://clients4.google.com/firefox/metrics/collect"; |
| 219 const char kServerUrlProto[] = "https://clients4.google.com/uma/v2"; |
| 207 | 220 |
| 208 // The delay, in seconds, after starting recording before doing expensive | 221 // The delay, in seconds, after starting recording before doing expensive |
| 209 // initialization work. | 222 // initialization work. |
| 210 static const int kInitializationDelaySeconds = 30; | 223 const int kInitializationDelaySeconds = 30; |
| 211 | 224 |
| 212 // This specifies the amount of time to wait for all renderers to send their | 225 // This specifies the amount of time to wait for all renderers to send their |
| 213 // data. | 226 // data. |
| 214 static const int kMaxHistogramGatheringWaitDuration = 60000; // 60 seconds. | 227 const int kMaxHistogramGatheringWaitDuration = 60000; // 60 seconds. |
| 215 | 228 |
| 216 // The maximum number of events in a log uploaded to the UMA server. | 229 // The maximum number of events in a log uploaded to the UMA server. |
| 217 static const int kEventLimit = 2400; | 230 const int kEventLimit = 2400; |
| 218 | 231 |
| 219 // If an upload fails, and the transmission was over this byte count, then we | 232 // If an upload fails, and the transmission was over this byte count, then we |
| 220 // will discard the log, and not try to retransmit it. We also don't persist | 233 // will discard the log, and not try to retransmit it. We also don't persist |
| 221 // the log to the prefs for transmission during the next chrome session if this | 234 // the log to the prefs for transmission during the next chrome session if this |
| 222 // limit is exceeded. | 235 // limit is exceeded. |
| 223 static const int kUploadLogAvoidRetransmitSize = 50000; | 236 const size_t kUploadLogAvoidRetransmitSize = 50000; |
| 224 | 237 |
| 225 // Interval, in minutes, between state saves. | 238 // Interval, in minutes, between state saves. |
| 226 static const int kSaveStateIntervalMinutes = 5; | 239 const int kSaveStateIntervalMinutes = 5; |
| 240 |
| 241 } |
| 227 | 242 |
| 228 // static | 243 // static |
| 229 MetricsService::ShutdownCleanliness MetricsService::clean_shutdown_status_ = | 244 MetricsService::ShutdownCleanliness MetricsService::clean_shutdown_status_ = |
| 230 MetricsService::CLEANLY_SHUTDOWN; | 245 MetricsService::CLEANLY_SHUTDOWN; |
| 231 | 246 |
| 232 // This is used to quickly log stats from child process related notifications in | 247 // This is used to quickly log stats from child process related notifications in |
| 233 // MetricsService::child_stats_buffer_. The buffer's contents are transferred | 248 // MetricsService::child_stats_buffer_. The buffer's contents are transferred |
| 234 // out when Local State is periodically saved. The information is then | 249 // out when Local State is periodically saved. The information is then |
| 235 // reported to the UMA server on next launch. | 250 // reported to the UMA server on next launch. |
| 236 struct MetricsService::ChildProcessStats { | 251 struct MetricsService::ChildProcessStats { |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 0); | 331 0); |
| 317 #endif // OS_CHROMEOS | 332 #endif // OS_CHROMEOS |
| 318 | 333 |
| 319 local_state->RegisterDictionaryPref(prefs::kProfileMetrics); | 334 local_state->RegisterDictionaryPref(prefs::kProfileMetrics); |
| 320 local_state->RegisterIntegerPref(prefs::kNumBookmarksOnBookmarkBar, 0); | 335 local_state->RegisterIntegerPref(prefs::kNumBookmarksOnBookmarkBar, 0); |
| 321 local_state->RegisterIntegerPref(prefs::kNumFoldersOnBookmarkBar, 0); | 336 local_state->RegisterIntegerPref(prefs::kNumFoldersOnBookmarkBar, 0); |
| 322 local_state->RegisterIntegerPref(prefs::kNumBookmarksInOtherBookmarkFolder, | 337 local_state->RegisterIntegerPref(prefs::kNumBookmarksInOtherBookmarkFolder, |
| 323 0); | 338 0); |
| 324 local_state->RegisterIntegerPref(prefs::kNumFoldersInOtherBookmarkFolder, 0); | 339 local_state->RegisterIntegerPref(prefs::kNumFoldersInOtherBookmarkFolder, 0); |
| 325 local_state->RegisterIntegerPref(prefs::kNumKeywords, 0); | 340 local_state->RegisterIntegerPref(prefs::kNumKeywords, 0); |
| 326 local_state->RegisterListPref(prefs::kMetricsInitialLogs); | 341 local_state->RegisterListPref(prefs::kMetricsInitialLogsXml); |
| 327 local_state->RegisterListPref(prefs::kMetricsOngoingLogs); | 342 local_state->RegisterListPref(prefs::kMetricsOngoingLogsXml); |
| 343 local_state->RegisterListPref(prefs::kMetricsInitialLogsProto); |
| 344 local_state->RegisterListPref(prefs::kMetricsOngoingLogsProto); |
| 328 | 345 |
| 329 local_state->RegisterInt64Pref(prefs::kUninstallMetricsPageLoadCount, 0); | 346 local_state->RegisterInt64Pref(prefs::kUninstallMetricsPageLoadCount, 0); |
| 330 local_state->RegisterInt64Pref(prefs::kUninstallLaunchCount, 0); | 347 local_state->RegisterInt64Pref(prefs::kUninstallLaunchCount, 0); |
| 331 local_state->RegisterInt64Pref(prefs::kUninstallMetricsInstallDate, 0); | 348 local_state->RegisterInt64Pref(prefs::kUninstallMetricsInstallDate, 0); |
| 332 local_state->RegisterInt64Pref(prefs::kUninstallMetricsUptimeSec, 0); | 349 local_state->RegisterInt64Pref(prefs::kUninstallMetricsUptimeSec, 0); |
| 333 local_state->RegisterInt64Pref(prefs::kUninstallLastLaunchTimeSec, 0); | 350 local_state->RegisterInt64Pref(prefs::kUninstallLastLaunchTimeSec, 0); |
| 334 local_state->RegisterInt64Pref(prefs::kUninstallLastObservedRunTimeSec, 0); | 351 local_state->RegisterInt64Pref(prefs::kUninstallLastObservedRunTimeSec, 0); |
| 335 } | 352 } |
| 336 | 353 |
| 337 // static | 354 // static |
| (...skipping 12 matching lines...) Expand all Loading... |
| 350 | 367 |
| 351 local_state->SetInteger(prefs::kStabilityPageLoadCount, 0); | 368 local_state->SetInteger(prefs::kStabilityPageLoadCount, 0); |
| 352 local_state->SetInteger(prefs::kStabilityRendererCrashCount, 0); | 369 local_state->SetInteger(prefs::kStabilityRendererCrashCount, 0); |
| 353 local_state->SetInteger(prefs::kStabilityRendererHangCount, 0); | 370 local_state->SetInteger(prefs::kStabilityRendererHangCount, 0); |
| 354 | 371 |
| 355 local_state->SetInt64(prefs::kStabilityLaunchTimeSec, 0); | 372 local_state->SetInt64(prefs::kStabilityLaunchTimeSec, 0); |
| 356 local_state->SetInt64(prefs::kStabilityLastTimestampSec, 0); | 373 local_state->SetInt64(prefs::kStabilityLastTimestampSec, 0); |
| 357 | 374 |
| 358 local_state->ClearPref(prefs::kStabilityPluginStats); | 375 local_state->ClearPref(prefs::kStabilityPluginStats); |
| 359 | 376 |
| 360 local_state->ClearPref(prefs::kMetricsInitialLogs); | 377 local_state->ClearPref(prefs::kMetricsInitialLogsXml); |
| 361 local_state->ClearPref(prefs::kMetricsOngoingLogs); | 378 local_state->ClearPref(prefs::kMetricsOngoingLogsXml); |
| 379 local_state->ClearPref(prefs::kMetricsInitialLogsProto); |
| 380 local_state->ClearPref(prefs::kMetricsOngoingLogsProto); |
| 362 } | 381 } |
| 363 | 382 |
| 364 MetricsService::MetricsService() | 383 MetricsService::MetricsService() |
| 365 : recording_active_(false), | 384 : recording_active_(false), |
| 366 reporting_active_(false), | 385 reporting_active_(false), |
| 367 state_(INITIALIZED), | 386 state_(INITIALIZED), |
| 368 current_fetch_(NULL), | |
| 369 io_thread_(NULL), | 387 io_thread_(NULL), |
| 370 idle_since_last_transmission_(false), | 388 idle_since_last_transmission_(false), |
| 371 next_window_id_(0), | 389 next_window_id_(0), |
| 372 ALLOW_THIS_IN_INITIALIZER_LIST(log_sender_factory_(this)), | 390 ALLOW_THIS_IN_INITIALIZER_LIST(log_sender_factory_(this)), |
| 373 ALLOW_THIS_IN_INITIALIZER_LIST(state_saver_factory_(this)), | 391 ALLOW_THIS_IN_INITIALIZER_LIST(state_saver_factory_(this)), |
| 374 waiting_for_asynchronus_reporting_step_(false) { | 392 waiting_for_asynchronus_reporting_step_(false) { |
| 375 DCHECK(IsSingleThreaded()); | 393 DCHECK(IsSingleThreaded()); |
| 376 InitializeMetricsState(); | 394 InitializeMetricsState(); |
| 377 | 395 |
| 378 base::Closure callback = base::Bind(&MetricsService::StartScheduledUpload, | 396 base::Closure callback = base::Bind(&MetricsService::StartScheduledUpload, |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 621 //------------------------------------------------------------------------------ | 639 //------------------------------------------------------------------------------ |
| 622 // private methods | 640 // private methods |
| 623 //------------------------------------------------------------------------------ | 641 //------------------------------------------------------------------------------ |
| 624 | 642 |
| 625 | 643 |
| 626 //------------------------------------------------------------------------------ | 644 //------------------------------------------------------------------------------ |
| 627 // Initialization methods | 645 // Initialization methods |
| 628 | 646 |
| 629 void MetricsService::InitializeMetricsState() { | 647 void MetricsService::InitializeMetricsState() { |
| 630 #if defined(OS_POSIX) | 648 #if defined(OS_POSIX) |
| 631 server_url_ = L"https://clients4.google.com/firefox/metrics/collect"; | 649 server_url_xml_ = ASCIIToUTF16(kServerUrlXml); |
| 650 server_url_proto_ = ASCIIToUTF16(kServerUrlProto); |
| 632 network_stats_server_ = "chrome.googleechotest.com"; | 651 network_stats_server_ = "chrome.googleechotest.com"; |
| 633 #else | 652 #else |
| 634 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); | 653 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
| 635 server_url_ = dist->GetStatsServerURL(); | 654 server_url_xml_ = dist->GetStatsServerURL(); |
| 655 server_url_proto_ = ASCIIToUTF16(kServerUrlProto); |
| 636 network_stats_server_ = dist->GetNetworkStatsServer(); | 656 network_stats_server_ = dist->GetNetworkStatsServer(); |
| 637 #endif | 657 #endif |
| 638 | 658 |
| 639 PrefService* pref = g_browser_process->local_state(); | 659 PrefService* pref = g_browser_process->local_state(); |
| 640 DCHECK(pref); | 660 DCHECK(pref); |
| 641 | 661 |
| 642 if ((pref->GetInt64(prefs::kStabilityStatsBuildTime) | 662 if ((pref->GetInt64(prefs::kStabilityStatsBuildTime) |
| 643 != MetricsLog::GetBuildTime()) || | 663 != MetricsLog::GetBuildTime()) || |
| 644 (pref->GetString(prefs::kStabilityStatsVersion) | 664 (pref->GetString(prefs::kStabilityStatsVersion) |
| 645 != MetricsLog::GetVersionString())) { | 665 != MetricsLog::GetVersionString())) { |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 832 // Adds to ongoing logs. | 852 // Adds to ongoing logs. |
| 833 log_manager_.current_log()->set_hardware_class(hardware_class_); | 853 log_manager_.current_log()->set_hardware_class(hardware_class_); |
| 834 | 854 |
| 835 // Put incremental data (histogram deltas, and realtime stats deltas) at the | 855 // Put incremental data (histogram deltas, and realtime stats deltas) at the |
| 836 // end of all log transmissions (initial log handles this separately). | 856 // end of all log transmissions (initial log handles this separately). |
| 837 // RecordIncrementalStabilityElements only exists on the derived | 857 // RecordIncrementalStabilityElements only exists on the derived |
| 838 // MetricsLog class. | 858 // MetricsLog class. |
| 839 MetricsLog* current_log = | 859 MetricsLog* current_log = |
| 840 static_cast<MetricsLog*>(log_manager_.current_log()); | 860 static_cast<MetricsLog*>(log_manager_.current_log()); |
| 841 DCHECK(current_log); | 861 DCHECK(current_log); |
| 842 current_log->RecordIncrementalStabilityElements(); | 862 current_log->RecordIncrementalStabilityElements(plugins_); |
| 843 RecordCurrentHistograms(); | 863 RecordCurrentHistograms(); |
| 844 | 864 |
| 845 log_manager_.StageCurrentLogForUpload(); | 865 log_manager_.StageCurrentLogForUpload(); |
| 846 } | 866 } |
| 847 | 867 |
| 848 void MetricsService::PushPendingLogsToPersistentStorage() { | 868 void MetricsService::PushPendingLogsToPersistentStorage() { |
| 849 if (state_ < INITIAL_LOG_READY) | 869 if (state_ < INITIAL_LOG_READY) |
| 850 return; // We didn't and still don't have time to get plugin list etc. | 870 return; // We didn't and still don't have time to get plugin list etc. |
| 851 | 871 |
| 852 if (log_manager_.has_staged_log()) { | 872 if (log_manager_.has_staged_log()) { |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 927 MessageLoop::current(), callback, | 947 MessageLoop::current(), callback, |
| 928 kMaxHistogramGatheringWaitDuration); | 948 kMaxHistogramGatheringWaitDuration); |
| 929 } | 949 } |
| 930 | 950 |
| 931 void MetricsService::OnHistogramSynchronizationDone() { | 951 void MetricsService::OnHistogramSynchronizationDone() { |
| 932 DCHECK(IsSingleThreaded()); | 952 DCHECK(IsSingleThreaded()); |
| 933 | 953 |
| 934 // If somehow there is a fetch in progress, we return and hope things work | 954 // If somehow there is a fetch in progress, we return and hope things work |
| 935 // out. The scheduler isn't informed since if this happens, the scheduler | 955 // out. The scheduler isn't informed since if this happens, the scheduler |
| 936 // will get a response from the upload. | 956 // will get a response from the upload. |
| 937 DCHECK(!current_fetch_.get()); | 957 DCHECK(!current_fetch_xml_.get()); |
| 938 if (current_fetch_.get()) | 958 DCHECK(!current_fetch_proto_.get()); |
| 959 if (current_fetch_xml_.get() || current_fetch_proto_.get()) |
| 939 return; | 960 return; |
| 940 | 961 |
| 941 // This function should only be called as the callback from an ansynchronous | 962 // This function should only be called as the callback from an ansynchronous |
| 942 // step. | 963 // step. |
| 943 DCHECK(waiting_for_asynchronus_reporting_step_); | 964 DCHECK(waiting_for_asynchronus_reporting_step_); |
| 944 waiting_for_asynchronus_reporting_step_ = false; | 965 waiting_for_asynchronus_reporting_step_ = false; |
| 945 | 966 |
| 946 // If we're getting no notifications, then the log won't have much in it, and | 967 // If we're getting no notifications, then the log won't have much in it, and |
| 947 // it's possible the computer is about to go to sleep, so don't upload and | 968 // it's possible the computer is about to go to sleep, so don't upload and |
| 948 // stop the scheduler. | 969 // stop the scheduler. |
| 949 // Similarly, if logs should no longer be uploaded, stop here. | 970 // Similarly, if logs should no longer be uploaded, stop here. |
| 950 if (idle_since_last_transmission_ || | 971 if (idle_since_last_transmission_ || |
| 951 !recording_active() || !reporting_active()) { | 972 !recording_active() || !reporting_active()) { |
| 952 scheduler_->Stop(); | 973 scheduler_->Stop(); |
| 953 scheduler_->UploadCancelled(); | 974 scheduler_->UploadCancelled(); |
| 954 return; | 975 return; |
| 955 } | 976 } |
| 956 | 977 |
| 957 MakeStagedLog(); | 978 MakeStagedLog(); |
| 958 | 979 |
| 959 // MakeStagedLog should have prepared log text; if it didn't, skip this | 980 // MakeStagedLog should have prepared log text; if it didn't, skip this |
| 960 // upload and hope things work out next time. | 981 // upload and hope things work out next time. |
| 961 if (log_manager_.staged_log_text().empty()) { | 982 if (log_manager_.staged_log_text().empty()) { |
| 962 scheduler_->UploadCancelled(); | 983 scheduler_->UploadCancelled(); |
| 963 return; | 984 return; |
| 964 } | 985 } |
| 965 | 986 |
| 966 PrepareFetchWithStagedLog(); | 987 PrepareFetchWithStagedLog(); |
| 967 | 988 |
| 968 if (!current_fetch_.get()) { | 989 if (!current_fetch_xml_.get()) { |
| 990 DCHECK(!current_fetch_proto_.get()); |
| 969 // Compression failed, and log discarded :-/. | 991 // Compression failed, and log discarded :-/. |
| 970 log_manager_.DiscardStagedLog(); | 992 log_manager_.DiscardStagedLog(); |
| 971 scheduler_->UploadCancelled(); | 993 scheduler_->UploadCancelled(); |
| 972 // TODO(jar): If compression failed, we should have created a tiny log and | 994 // TODO(jar): If compression failed, we should have created a tiny log and |
| 973 // compressed that, so that we can signal that we're losing logs. | 995 // compressed that, so that we can signal that we're losing logs. |
| 974 return; | 996 return; |
| 975 } | 997 } |
| 998 // Currently, the staged log for the protobuf version of the data is discarded |
| 999 // after we create the URL request, so that there is no chance for |
| 1000 // re-transmission in case the corresponding XML request fails. We will |
| 1001 // handle protobuf failures more carefully once that becomes the main |
| 1002 // pipeline, i.e. once we switch away from the XML pipeline. |
| 1003 DCHECK(current_fetch_proto_.get() || !log_manager_.has_staged_log_proto()); |
| 976 | 1004 |
| 977 DCHECK(!waiting_for_asynchronus_reporting_step_); | 1005 DCHECK(!waiting_for_asynchronus_reporting_step_); |
| 978 | 1006 |
| 979 waiting_for_asynchronus_reporting_step_ = true; | 1007 waiting_for_asynchronus_reporting_step_ = true; |
| 980 current_fetch_->Start(); | 1008 current_fetch_xml_->Start(); |
| 1009 if (current_fetch_proto_.get()) |
| 1010 current_fetch_proto_->Start(); |
| 981 | 1011 |
| 982 HandleIdleSinceLastTransmission(true); | 1012 HandleIdleSinceLastTransmission(true); |
| 983 } | 1013 } |
| 984 | 1014 |
| 985 | 1015 |
| 986 void MetricsService::MakeStagedLog() { | 1016 void MetricsService::MakeStagedLog() { |
| 987 if (log_manager_.has_staged_log()) | 1017 if (log_manager_.has_staged_log()) |
| 988 return; | 1018 return; |
| 989 | 1019 |
| 990 switch (state_) { | 1020 switch (state_) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1044 | 1074 |
| 1045 void MetricsService::StoreUnsentLogs() { | 1075 void MetricsService::StoreUnsentLogs() { |
| 1046 if (state_ < INITIAL_LOG_READY) | 1076 if (state_ < INITIAL_LOG_READY) |
| 1047 return; // We never Recalled the prior unsent logs. | 1077 return; // We never Recalled the prior unsent logs. |
| 1048 | 1078 |
| 1049 log_manager_.PersistUnsentLogs(); | 1079 log_manager_.PersistUnsentLogs(); |
| 1050 } | 1080 } |
| 1051 | 1081 |
| 1052 void MetricsService::PrepareFetchWithStagedLog() { | 1082 void MetricsService::PrepareFetchWithStagedLog() { |
| 1053 DCHECK(!log_manager_.staged_log_text().empty()); | 1083 DCHECK(!log_manager_.staged_log_text().empty()); |
| 1054 DCHECK(!current_fetch_.get()); | |
| 1055 | 1084 |
| 1056 current_fetch_.reset(content::URLFetcher::Create( | 1085 // Prepare the XML version. |
| 1057 GURL(WideToUTF16(server_url_)), content::URLFetcher::POST, this)); | 1086 DCHECK(!current_fetch_xml_.get()); |
| 1058 current_fetch_->SetRequestContext( | 1087 current_fetch_xml_.reset(content::URLFetcher::Create( |
| 1088 GURL(server_url_xml_), content::URLFetcher::POST, this)); |
| 1089 current_fetch_xml_->SetRequestContext( |
| 1059 g_browser_process->system_request_context()); | 1090 g_browser_process->system_request_context()); |
| 1060 current_fetch_->SetUploadData(kMetricsType, log_manager_.staged_log_text()); | 1091 current_fetch_xml_->SetUploadData(kMetricsTypeXml, |
| 1092 log_manager_.staged_log_text().xml); |
| 1093 // We already drop cookies server-side, but we might as well strip them out |
| 1094 // client-side as well. |
| 1095 current_fetch_xml_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | |
| 1096 net::LOAD_DO_NOT_SEND_COOKIES); |
| 1097 |
| 1098 // Prepare the protobuf version. |
| 1099 DCHECK(!current_fetch_proto_.get()); |
| 1100 if (log_manager_.has_staged_log_proto()) { |
| 1101 current_fetch_proto_.reset(content::URLFetcher::Create( |
| 1102 GURL(server_url_proto_), content::URLFetcher::POST, this)); |
| 1103 current_fetch_proto_->SetRequestContext( |
| 1104 g_browser_process->system_request_context()); |
| 1105 current_fetch_proto_->SetUploadData(kMetricsTypeProto, |
| 1106 log_manager_.staged_log_text().proto); |
| 1107 // We already drop cookies server-side, but we might as well strip them out |
| 1108 // client-side as well. |
| 1109 current_fetch_proto_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | |
| 1110 net::LOAD_DO_NOT_SEND_COOKIES); |
| 1111 |
| 1112 // Discard the protobuf version of the staged log, so that we will avoid |
| 1113 // re-uploading it even if we need to re-upload the XML version. |
| 1114 // TODO(isherman): Handle protobuf upload failures more gracefully once we |
| 1115 // transition away from the XML-based pipeline. |
| 1116 log_manager_.DiscardStagedLogProto(); |
| 1117 } |
| 1061 } | 1118 } |
| 1062 | 1119 |
| 1063 static const char* StatusToString(const net::URLRequestStatus& status) { | 1120 static const char* StatusToString(const net::URLRequestStatus& status) { |
| 1064 switch (status.status()) { | 1121 switch (status.status()) { |
| 1065 case net::URLRequestStatus::SUCCESS: | 1122 case net::URLRequestStatus::SUCCESS: |
| 1066 return "SUCCESS"; | 1123 return "SUCCESS"; |
| 1067 | 1124 |
| 1068 case net::URLRequestStatus::IO_PENDING: | 1125 case net::URLRequestStatus::IO_PENDING: |
| 1069 return "IO_PENDING"; | 1126 return "IO_PENDING"; |
| 1070 | 1127 |
| 1071 case net::URLRequestStatus::HANDLED_EXTERNALLY: | 1128 case net::URLRequestStatus::HANDLED_EXTERNALLY: |
| 1072 return "HANDLED_EXTERNALLY"; | 1129 return "HANDLED_EXTERNALLY"; |
| 1073 | 1130 |
| 1074 case net::URLRequestStatus::CANCELED: | 1131 case net::URLRequestStatus::CANCELED: |
| 1075 return "CANCELED"; | 1132 return "CANCELED"; |
| 1076 | 1133 |
| 1077 case net::URLRequestStatus::FAILED: | 1134 case net::URLRequestStatus::FAILED: |
| 1078 return "FAILED"; | 1135 return "FAILED"; |
| 1079 | 1136 |
| 1080 default: | 1137 default: |
| 1081 NOTREACHED(); | 1138 NOTREACHED(); |
| 1082 return "Unknown"; | 1139 return "Unknown"; |
| 1083 } | 1140 } |
| 1084 } | 1141 } |
| 1085 | 1142 |
| 1143 // We need to wait for two responses: the response to the XML upload, and the |
| 1144 // response to the protobuf upload. For now, only the XML upload's response |
| 1145 // affects decisions like whether to retry the upload, whether to abandon the |
| 1146 // upload because it is too large, etc. However, we still need to wait for the |
| 1147 // protobuf upload, as we cannot reset |current_fetch_proto_| until we have |
| 1148 // confirmation that the network request was sent; and the easiest way to do |
| 1149 // that is to wait for the response. In case the XML upload's response arrives |
| 1150 // first, we cache that response until the protobuf upload's response also |
| 1151 // arrives. |
| 1152 // |
| 1153 // Note that if the XML upload succeeds but the protobuf upload fails, we will |
| 1154 // not retry the protobuf upload. If the XML upload fails while the protobuf |
| 1155 // upload succeeds, we will still avoid re-uploading the protobuf data because |
| 1156 // we "zap" the data after the first upload attempt. This means that we might |
| 1157 // lose protobuf uploads when XML ones succeed; but we will never duplicate any |
| 1158 // protobuf uploads. Protobuf failures should be rare enough to where this |
| 1159 // should be ok while we have the two pipelines running in parallel. |
| 1086 void MetricsService::OnURLFetchComplete(const content::URLFetcher* source) { | 1160 void MetricsService::OnURLFetchComplete(const content::URLFetcher* source) { |
| 1087 DCHECK(waiting_for_asynchronus_reporting_step_); | 1161 DCHECK(waiting_for_asynchronus_reporting_step_); |
| 1162 |
| 1163 // We're not allowed to re-use the existing |URLFetcher|s, so free them here. |
| 1164 scoped_ptr<content::URLFetcher> s; |
| 1165 if (source == current_fetch_xml_.get()) { |
| 1166 s.reset(current_fetch_xml_.release()); |
| 1167 |
| 1168 // Cache the XML responses, in case we still need to wait for the protobuf |
| 1169 // response. |
| 1170 response_code_ = source->GetResponseCode(); |
| 1171 response_status_ = StatusToString(source->GetStatus()); |
| 1172 source->GetResponseAsString(&response_data_); |
| 1173 } else if (source == current_fetch_proto_.get()) { |
| 1174 s.reset(current_fetch_proto_.release()); |
| 1175 } else { |
| 1176 NOTREACHED(); |
| 1177 return; |
| 1178 } |
| 1179 |
| 1180 // If we're still waiting for one of the responses, keep waiting... |
| 1181 if (current_fetch_xml_.get() || current_fetch_proto_.get()) |
| 1182 return; |
| 1183 |
| 1184 // We should only be able to reach here once we've received responses to both |
| 1185 // the XML and the protobuf requests. We should always have the response code |
| 1186 // available. |
| 1187 DCHECK_NE(response_code_, content::URLFetcher::RESPONSE_CODE_INVALID); |
| 1088 waiting_for_asynchronus_reporting_step_ = false; | 1188 waiting_for_asynchronus_reporting_step_ = false; |
| 1089 DCHECK(current_fetch_.get()); | 1189 |
| 1090 // We're not allowed to re-use it. Delete it on function exit since we use it. | |
| 1091 scoped_ptr<content::URLFetcher> s(current_fetch_.release()); | |
| 1092 | 1190 |
| 1093 // Confirm send so that we can move on. | 1191 // Confirm send so that we can move on. |
| 1094 VLOG(1) << "METRICS RESPONSE CODE: " << source->GetResponseCode() | 1192 VLOG(1) << "METRICS RESPONSE CODE: " << response_code_ |
| 1095 << " status=" << StatusToString(source->GetStatus()); | 1193 << " status=" << response_status_; |
| 1096 | 1194 |
| 1097 bool upload_succeeded = source->GetResponseCode() == 200; | 1195 bool upload_succeeded = response_code_ == 200; |
| 1098 | 1196 |
| 1099 // Provide boolean for error recovery (allow us to ignore response_code). | 1197 // Provide boolean for error recovery (allow us to ignore response_code). |
| 1100 bool discard_log = false; | 1198 bool discard_log = false; |
| 1101 | 1199 |
| 1102 if (!upload_succeeded && | 1200 if (!upload_succeeded && |
| 1103 (log_manager_.staged_log_text().length() > | 1201 log_manager_.staged_log_text().xml.length() > |
| 1104 static_cast<size_t>(kUploadLogAvoidRetransmitSize))) { | 1202 kUploadLogAvoidRetransmitSize) { |
| 1105 UMA_HISTOGRAM_COUNTS( | 1203 UMA_HISTOGRAM_COUNTS( |
| 1106 "UMA.Large Rejected Log was Discarded", | 1204 "UMA.Large Rejected Log was Discarded", |
| 1107 static_cast<int>(log_manager_.staged_log_text().length())); | 1205 static_cast<int>(log_manager_.staged_log_text().xml.length())); |
| 1108 discard_log = true; | 1206 discard_log = true; |
| 1109 } else if (source->GetResponseCode() == 400) { | 1207 } else if (response_code_ == 400) { |
| 1110 // Bad syntax. Retransmission won't work. | 1208 // Bad syntax. Retransmission won't work. |
| 1111 UMA_HISTOGRAM_COUNTS("UMA.Unacceptable_Log_Discarded", state_); | 1209 UMA_HISTOGRAM_COUNTS("UMA.Unacceptable_Log_Discarded", state_); |
| 1112 discard_log = true; | 1210 discard_log = true; |
| 1113 } | 1211 } |
| 1114 | 1212 |
| 1115 if (!upload_succeeded && !discard_log) { | 1213 if (!upload_succeeded && !discard_log) { |
| 1116 VLOG(1) << "METRICS: transmission attempt returned a failure code: " | 1214 VLOG(1) << "METRICS: transmission attempt returned a failure code: " |
| 1117 << source->GetResponseCode() << ". Verify network connectivity"; | 1215 << response_code_ << ". Verify network connectivity"; |
| 1118 LogBadResponseCode(); | 1216 LogBadResponseCode(); |
| 1119 } else { // Successful receipt (or we are discarding log). | 1217 } else { // Successful receipt (or we are discarding log). |
| 1120 std::string data; | 1218 VLOG(1) << "METRICS RESPONSE DATA: " << response_data_; |
| 1121 source->GetResponseAsString(&data); | |
| 1122 VLOG(1) << "METRICS RESPONSE DATA: " << data; | |
| 1123 switch (state_) { | 1219 switch (state_) { |
| 1124 case INITIAL_LOG_READY: | 1220 case INITIAL_LOG_READY: |
| 1125 state_ = SENDING_OLD_LOGS; | 1221 state_ = SENDING_OLD_LOGS; |
| 1126 break; | 1222 break; |
| 1127 | 1223 |
| 1128 case SENDING_OLD_LOGS: | 1224 case SENDING_OLD_LOGS: |
| 1129 // Store the updated list to disk now that the removed log is uploaded. | 1225 // Store the updated list to disk now that the removed log is uploaded. |
| 1130 StoreUnsentLogs(); | 1226 StoreUnsentLogs(); |
| 1131 break; | 1227 break; |
| 1132 | 1228 |
| 1133 case SENDING_CURRENT_LOGS: | 1229 case SENDING_CURRENT_LOGS: |
| 1134 break; | 1230 break; |
| 1135 | 1231 |
| 1136 default: | 1232 default: |
| 1137 NOTREACHED(); | 1233 NOTREACHED(); |
| 1138 break; | 1234 break; |
| 1139 } | 1235 } |
| 1140 | 1236 |
| 1141 log_manager_.DiscardStagedLog(); | 1237 log_manager_.DiscardStagedLog(); |
| 1142 | 1238 |
| 1143 if (log_manager_.has_unsent_logs()) | 1239 if (log_manager_.has_unsent_logs()) |
| 1144 DCHECK(state_ < SENDING_CURRENT_LOGS); | 1240 DCHECK(state_ < SENDING_CURRENT_LOGS); |
| 1145 } | 1241 } |
| 1146 | 1242 |
| 1147 // Error 400 indicates a problem with the log, not with the server, so | 1243 // Error 400 indicates a problem with the log, not with the server, so |
| 1148 // don't consider that a sign that the server is in trouble. | 1244 // don't consider that a sign that the server is in trouble. |
| 1149 bool server_is_healthy = upload_succeeded || source->GetResponseCode() == 400; | 1245 bool server_is_healthy = upload_succeeded || response_code_ == 400; |
| 1150 | 1246 |
| 1151 scheduler_->UploadFinished(server_is_healthy, | 1247 scheduler_->UploadFinished(server_is_healthy, |
| 1152 log_manager_.has_unsent_logs()); | 1248 log_manager_.has_unsent_logs()); |
| 1153 | 1249 |
| 1154 // Collect network stats if UMA upload succeeded. | 1250 // Collect network stats if UMA upload succeeded. |
| 1155 if (server_is_healthy && io_thread_) | 1251 if (server_is_healthy && io_thread_) |
| 1156 chrome_browser_net::CollectNetworkStats(network_stats_server_, io_thread_); | 1252 chrome_browser_net::CollectNetworkStats(network_stats_server_, io_thread_); |
| 1253 |
| 1254 // Reset the cached response data. |
| 1255 response_code_ = content::URLFetcher::RESPONSE_CODE_INVALID; |
| 1256 response_data_ = std::string(); |
| 1257 response_status_ = std::string(); |
| 1157 } | 1258 } |
| 1158 | 1259 |
| 1159 void MetricsService::LogBadResponseCode() { | 1260 void MetricsService::LogBadResponseCode() { |
| 1160 VLOG(1) << "Verify your metrics logs are formatted correctly. Verify server " | 1261 VLOG(1) << "Verify your metrics logs are formatted correctly. Verify server " |
| 1161 "is active at " << server_url_; | 1262 "is active at " << server_url_xml_; |
| 1162 if (!log_manager_.has_staged_log()) { | 1263 if (!log_manager_.has_staged_log()) { |
| 1163 VLOG(1) << "METRICS: Recorder shutdown during log transmission."; | 1264 VLOG(1) << "METRICS: Recorder shutdown during log transmission."; |
| 1164 } else { | 1265 } else { |
| 1165 VLOG(1) << "METRICS: transmission retry being scheduled for " | 1266 VLOG(1) << "METRICS: transmission retry being scheduled for " |
| 1166 << log_manager_.staged_log_text(); | 1267 << log_manager_.staged_log_text().xml; |
| 1167 } | 1268 } |
| 1168 } | 1269 } |
| 1169 | 1270 |
| 1170 void MetricsService::LogWindowChange( | 1271 void MetricsService::LogWindowChange( |
| 1171 int type, | 1272 int type, |
| 1172 const content::NotificationSource& source, | 1273 const content::NotificationSource& source, |
| 1173 const content::NotificationDetails& details) { | 1274 const content::NotificationDetails& details) { |
| 1174 int controller_id = -1; | 1275 int controller_id = -1; |
| 1175 uintptr_t window_or_tab = source.map_key(); | 1276 uintptr_t window_or_tab = source.map_key(); |
| 1176 MetricsLog::WindowEventType window_type; | 1277 MetricsLog::WindowEventType window_type; |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1528 | 1629 |
| 1529 RecordPluginChanges(pref); | 1630 RecordPluginChanges(pref); |
| 1530 } | 1631 } |
| 1531 | 1632 |
| 1532 // static | 1633 // static |
| 1533 bool MetricsService::IsPluginProcess(content::ProcessType type) { | 1634 bool MetricsService::IsPluginProcess(content::ProcessType type) { |
| 1534 return (type == content::PROCESS_TYPE_PLUGIN|| | 1635 return (type == content::PROCESS_TYPE_PLUGIN|| |
| 1535 type == content::PROCESS_TYPE_PPAPI_PLUGIN); | 1636 type == content::PROCESS_TYPE_PPAPI_PLUGIN); |
| 1536 } | 1637 } |
| 1537 | 1638 |
| 1538 static bool IsSingleThreaded() { | |
| 1539 static base::PlatformThreadId thread_id = 0; | |
| 1540 if (!thread_id) | |
| 1541 thread_id = base::PlatformThread::CurrentId(); | |
| 1542 return base::PlatformThread::CurrentId() == thread_id; | |
| 1543 } | |
| 1544 | |
| 1545 #if defined(OS_CHROMEOS) | 1639 #if defined(OS_CHROMEOS) |
| 1546 void MetricsService::StartExternalMetrics() { | 1640 void MetricsService::StartExternalMetrics() { |
| 1547 external_metrics_ = new chromeos::ExternalMetrics; | 1641 external_metrics_ = new chromeos::ExternalMetrics; |
| 1548 external_metrics_->Start(); | 1642 external_metrics_->Start(); |
| 1549 } | 1643 } |
| 1550 #endif | 1644 #endif |
| 1551 | 1645 |
| 1552 // static | 1646 // static |
| 1553 bool MetricsServiceHelper::IsMetricsReportingEnabled() { | 1647 bool MetricsServiceHelper::IsMetricsReportingEnabled() { |
| 1554 bool result = false; | 1648 bool result = false; |
| 1555 const PrefService* local_state = g_browser_process->local_state(); | 1649 const PrefService* local_state = g_browser_process->local_state(); |
| 1556 if (local_state) { | 1650 if (local_state) { |
| 1557 const PrefService::Preference* uma_pref = | 1651 const PrefService::Preference* uma_pref = |
| 1558 local_state->FindPreference(prefs::kMetricsReportingEnabled); | 1652 local_state->FindPreference(prefs::kMetricsReportingEnabled); |
| 1559 if (uma_pref) { | 1653 if (uma_pref) { |
| 1560 bool success = uma_pref->GetValue()->GetAsBoolean(&result); | 1654 bool success = uma_pref->GetValue()->GetAsBoolean(&result); |
| 1561 DCHECK(success); | 1655 DCHECK(success); |
| 1562 } | 1656 } |
| 1563 } | 1657 } |
| 1564 return result; | 1658 return result; |
| 1565 } | 1659 } |
| OLD | NEW |