| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 // the external server, and the user shuts down, then a copy of the log may be | 150 // the external server, and the user shuts down, then a copy of the log may be |
| 151 // saved for re-transmission. These duplicates could be filtered out server | 151 // saved for re-transmission. These duplicates could be filtered out server |
| 152 // side, but are not expected to be a significant problem. | 152 // side, but are not expected to be a significant problem. |
| 153 // | 153 // |
| 154 // | 154 // |
| 155 //------------------------------------------------------------------------------ | 155 //------------------------------------------------------------------------------ |
| 156 | 156 |
| 157 #include "chrome/browser/metrics/metrics_service.h" | 157 #include "chrome/browser/metrics/metrics_service.h" |
| 158 | 158 |
| 159 #include "base/base64.h" | 159 #include "base/base64.h" |
| 160 #include "base/bind.h" |
| 161 #include "base/callback.h" |
| 160 #include "base/command_line.h" | 162 #include "base/command_line.h" |
| 161 #include "base/md5.h" | 163 #include "base/md5.h" |
| 162 #include "base/metrics/histogram.h" | 164 #include "base/metrics/histogram.h" |
| 163 #include "base/string_number_conversions.h" | 165 #include "base/string_number_conversions.h" |
| 164 #include "base/threading/platform_thread.h" | 166 #include "base/threading/platform_thread.h" |
| 165 #include "base/threading/thread.h" | 167 #include "base/threading/thread.h" |
| 166 #include "base/utf_string_conversions.h" | 168 #include "base/utf_string_conversions.h" |
| 167 #include "base/values.h" | 169 #include "base/values.h" |
| 168 #include "chrome/browser/bookmarks/bookmark_model.h" | 170 #include "chrome/browser/bookmarks/bookmark_model.h" |
| 169 #include "chrome/browser/browser_process.h" | 171 #include "chrome/browser/browser_process.h" |
| 170 #include "chrome/browser/load_notification_details.h" | 172 #include "chrome/browser/load_notification_details.h" |
| 171 #include "chrome/browser/memory_details.h" | 173 #include "chrome/browser/memory_details.h" |
| 172 #include "chrome/browser/metrics/histogram_synchronizer.h" | 174 #include "chrome/browser/metrics/histogram_synchronizer.h" |
| 173 #include "chrome/browser/metrics/metrics_log.h" | 175 #include "chrome/browser/metrics/metrics_log.h" |
| 176 #include "chrome/browser/metrics/metrics_reporting_scheduler.h" |
| 174 #include "chrome/browser/prefs/pref_service.h" | 177 #include "chrome/browser/prefs/pref_service.h" |
| 175 #include "chrome/browser/prefs/scoped_user_pref_update.h" | 178 #include "chrome/browser/prefs/scoped_user_pref_update.h" |
| 176 #include "chrome/browser/profiles/profile.h" | 179 #include "chrome/browser/profiles/profile.h" |
| 177 #include "chrome/browser/search_engines/template_url_model.h" | 180 #include "chrome/browser/search_engines/template_url_model.h" |
| 178 #include "chrome/browser/ui/browser_list.h" | 181 #include "chrome/browser/ui/browser_list.h" |
| 179 #include "chrome/common/child_process_logging.h" | 182 #include "chrome/common/child_process_logging.h" |
| 180 #include "chrome/common/chrome_switches.h" | 183 #include "chrome/common/chrome_switches.h" |
| 181 #include "chrome/common/guid.h" | 184 #include "chrome/common/guid.h" |
| 182 #include "chrome/common/pref_names.h" | 185 #include "chrome/common/pref_names.h" |
| 183 #include "chrome/common/render_messages.h" | 186 #include "chrome/common/render_messages.h" |
| 184 #include "content/browser/renderer_host/render_process_host.h" | 187 #include "content/browser/renderer_host/render_process_host.h" |
| 185 #include "content/common/child_process_info.h" | 188 #include "content/common/child_process_info.h" |
| 186 #include "content/common/notification_service.h" | 189 #include "content/common/notification_service.h" |
| 187 #include "libxml/xmlwriter.h" | |
| 188 #include "webkit/plugins/npapi/plugin_list.h" | 190 #include "webkit/plugins/npapi/plugin_list.h" |
| 189 #include "webkit/plugins/npapi/webplugininfo.h" | 191 #include "webkit/plugins/npapi/webplugininfo.h" |
| 190 | 192 |
| 191 // TODO(port): port browser_distribution.h. | 193 // TODO(port): port browser_distribution.h. |
| 192 #if !defined(OS_POSIX) | 194 #if !defined(OS_POSIX) |
| 193 #include "chrome/installer/util/browser_distribution.h" | 195 #include "chrome/installer/util/browser_distribution.h" |
| 194 #endif | 196 #endif |
| 195 | 197 |
| 196 #if defined(OS_CHROMEOS) | 198 #if defined(OS_CHROMEOS) |
| 197 #include "chrome/browser/chromeos/cros/cros_library.h" | 199 #include "chrome/browser/chromeos/cros/cros_library.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 208 } | 210 } |
| 209 | 211 |
| 210 // TODO(ziadh): Remove this when done with experiment. | 212 // TODO(ziadh): Remove this when done with experiment. |
| 211 void MakeStoreStatusHistogram(MetricsService::LogStoreStatus status) { | 213 void MakeStoreStatusHistogram(MetricsService::LogStoreStatus status) { |
| 212 UMA_HISTOGRAM_ENUMERATION("PrefService.PersistentLogStore2", status, | 214 UMA_HISTOGRAM_ENUMERATION("PrefService.PersistentLogStore2", status, |
| 213 MetricsService::END_STORE_STATUS); | 215 MetricsService::END_STORE_STATUS); |
| 214 } | 216 } |
| 215 } // namespace | 217 } // namespace |
| 216 | 218 |
| 217 using base::Time; | 219 using base::Time; |
| 218 using base::TimeDelta; | |
| 219 | 220 |
| 220 // Check to see that we're being called on only one thread. | 221 // Check to see that we're being called on only one thread. |
| 221 static bool IsSingleThreaded(); | 222 static bool IsSingleThreaded(); |
| 222 | 223 |
| 223 static const char kMetricsType[] = "application/vnd.mozilla.metrics.bz2"; | 224 static const char kMetricsType[] = "application/vnd.mozilla.metrics.bz2"; |
| 224 | 225 |
| 225 // The delay, in seconds, after startup before sending the first log message. | 226 // The delay, in seconds, after starting recording before doing expensive |
| 226 static const int kInitialInterlogDuration = 60; // one minute | 227 // initialization work. |
| 228 static const int kInitializationDelaySeconds = 30; |
| 227 | 229 |
| 228 // This specifies the amount of time to wait for all renderers to send their | 230 // This specifies the amount of time to wait for all renderers to send their |
| 229 // data. | 231 // data. |
| 230 static const int kMaxHistogramGatheringWaitDuration = 60000; // 60 seconds. | 232 static const int kMaxHistogramGatheringWaitDuration = 60000; // 60 seconds. |
| 231 | 233 |
| 232 // The maximum number of events in a log uploaded to the UMA server. | 234 // The maximum number of events in a log uploaded to the UMA server. |
| 233 static const int kEventLimit = 2400; | 235 static const int kEventLimit = 2400; |
| 234 | 236 |
| 235 // If an upload fails, and the transmission was over this byte count, then we | 237 // If an upload fails, and the transmission was over this byte count, then we |
| 236 // will discard the log, and not try to retransmit it. We also don't persist | 238 // will discard the log, and not try to retransmit it. We also don't persist |
| 237 // the log to the prefs for transmission during the next chrome session if this | 239 // the log to the prefs for transmission during the next chrome session if this |
| 238 // limit is exceeded. | 240 // limit is exceeded. |
| 239 static const int kUploadLogAvoidRetransmitSize = 50000; | 241 static const int kUploadLogAvoidRetransmitSize = 50000; |
| 240 | 242 |
| 241 // When we have logs from previous Chrome sessions to send, how long should we | |
| 242 // delay (in seconds) between each log transmission. | |
| 243 static const int kUnsentLogDelay = 15; // 15 seconds | |
| 244 | |
| 245 // Minimum time a log typically exists before sending, in seconds. | |
| 246 // This number is supplied by the server, but until we parse it out of a server | |
| 247 // response, we use this duration to specify how long we should wait before | |
| 248 // sending the next log. If the channel is busy, such as when there is a | |
| 249 // failure during an attempt to transmit a previous log, then a log may wait | |
| 250 // (and continue to accrue new log entries) for a much greater period of time. | |
| 251 static const int kMinSecondsPerLog = 30 * 60; // Thirty minutes. | |
| 252 | |
| 253 // When we don't succeed at transmitting a log to a server, we progressively | |
| 254 // wait longer and longer before sending the next log. This backoff process | |
| 255 // help reduce load on the server, and makes the amount of backoff vary between | |
| 256 // clients so that a collision (server overload?) on retransmit is less likely. | |
| 257 // The following is the constant we use to expand that inter-log duration. | |
| 258 static const double kBackoff = 1.1; | |
| 259 // We limit the maximum backoff to be no greater than some multiple of the | |
| 260 // default kMinSecondsPerLog. The following is that maximum ratio. | |
| 261 static const int kMaxBackoff = 10; | |
| 262 | |
| 263 // Interval, in seconds, between state saves. | 243 // Interval, in seconds, between state saves. |
| 264 static const int kSaveStateInterval = 5 * 60; // five minutes | 244 static const int kSaveStateInterval = 5 * 60; // five minutes |
| 265 | 245 |
| 266 // The number of "initial" logs we're willing to save, and hope to send during | 246 // The number of "initial" logs we're willing to save, and hope to send during |
| 267 // a future Chrome session. Initial logs contain crash stats, and are pretty | 247 // a future Chrome session. Initial logs contain crash stats, and are pretty |
| 268 // small. | 248 // small. |
| 269 static const size_t kMaxInitialLogsPersisted = 20; | 249 static const size_t kMaxInitialLogsPersisted = 20; |
| 270 | 250 |
| 271 // The number of ongoing logs we're willing to save persistently, and hope to | 251 // The number of ongoing logs we're willing to save persistently, and hope to |
| 272 // send during a this or future sessions. Note that each log may be pretty | 252 // send during a this or future sessions. Note that each log may be pretty |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 448 | 428 |
| 449 local_state->ClearPref(prefs::kStabilityPluginStats); | 429 local_state->ClearPref(prefs::kStabilityPluginStats); |
| 450 | 430 |
| 451 local_state->ClearPref(prefs::kMetricsInitialLogs); | 431 local_state->ClearPref(prefs::kMetricsInitialLogs); |
| 452 local_state->ClearPref(prefs::kMetricsOngoingLogs); | 432 local_state->ClearPref(prefs::kMetricsOngoingLogs); |
| 453 } | 433 } |
| 454 | 434 |
| 455 MetricsService::MetricsService() | 435 MetricsService::MetricsService() |
| 456 : recording_active_(false), | 436 : recording_active_(false), |
| 457 reporting_active_(false), | 437 reporting_active_(false), |
| 458 server_permits_upload_(true), | |
| 459 state_(INITIALIZED), | 438 state_(INITIALIZED), |
| 460 current_fetch_(NULL), | 439 current_fetch_(NULL), |
| 461 idle_since_last_transmission_(false), | 440 idle_since_last_transmission_(false), |
| 462 next_window_id_(0), | 441 next_window_id_(0), |
| 463 ALLOW_THIS_IN_INITIALIZER_LIST(log_sender_factory_(this)), | 442 ALLOW_THIS_IN_INITIALIZER_LIST(log_sender_factory_(this)), |
| 464 ALLOW_THIS_IN_INITIALIZER_LIST(state_saver_factory_(this)), | 443 ALLOW_THIS_IN_INITIALIZER_LIST(state_saver_factory_(this)), |
| 465 interlog_duration_(TimeDelta::FromSeconds(kInitialInterlogDuration)), | 444 waiting_for_asynchronus_reporting_step_(false) { |
| 466 timer_pending_(false) { | |
| 467 DCHECK(IsSingleThreaded()); | 445 DCHECK(IsSingleThreaded()); |
| 468 InitializeMetricsState(); | 446 InitializeMetricsState(); |
| 447 |
| 448 base::Closure callback = base::Bind(&MetricsService::StartScheduledUpload, |
| 449 base::Unretained(this)); |
| 450 scheduler_.reset(new MetricsReportingScheduler(callback)); |
| 469 } | 451 } |
| 470 | 452 |
| 471 MetricsService::~MetricsService() { | 453 MetricsService::~MetricsService() { |
| 472 SetRecording(false); | 454 SetRecording(false); |
| 473 } | 455 } |
| 474 | 456 |
| 475 void MetricsService::Start() { | 457 void MetricsService::Start() { |
| 476 HandleIdleSinceLastTransmission(false); | 458 HandleIdleSinceLastTransmission(false); |
| 477 SetRecording(true); | 459 SetRecording(true); |
| 478 SetReporting(true); | 460 SetReporting(true); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 | 507 |
| 526 bool MetricsService::recording_active() const { | 508 bool MetricsService::recording_active() const { |
| 527 DCHECK(IsSingleThreaded()); | 509 DCHECK(IsSingleThreaded()); |
| 528 return recording_active_; | 510 return recording_active_; |
| 529 } | 511 } |
| 530 | 512 |
| 531 void MetricsService::SetReporting(bool enable) { | 513 void MetricsService::SetReporting(bool enable) { |
| 532 if (reporting_active_ != enable) { | 514 if (reporting_active_ != enable) { |
| 533 reporting_active_ = enable; | 515 reporting_active_ = enable; |
| 534 if (reporting_active_) | 516 if (reporting_active_) |
| 535 StartLogTransmissionTimer(); | 517 StartSchedulerIfNecessary(); |
| 536 } | 518 } |
| 537 } | 519 } |
| 538 | 520 |
| 539 bool MetricsService::reporting_active() const { | 521 bool MetricsService::reporting_active() const { |
| 540 DCHECK(IsSingleThreaded()); | 522 DCHECK(IsSingleThreaded()); |
| 541 return reporting_active_; | 523 return reporting_active_; |
| 542 } | 524 } |
| 543 | 525 |
| 544 // static | 526 // static |
| 545 void MetricsService::SetUpNotifications(NotificationRegistrar* registrar, | 527 void MetricsService::SetUpNotifications(NotificationRegistrar* registrar, |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 661 | 643 |
| 662 if (current_log_) | 644 if (current_log_) |
| 663 DVLOG(1) << "METRICS: NUMBER OF EVENTS = " << current_log_->num_events(); | 645 DVLOG(1) << "METRICS: NUMBER OF EVENTS = " << current_log_->num_events(); |
| 664 } | 646 } |
| 665 | 647 |
| 666 void MetricsService::HandleIdleSinceLastTransmission(bool in_idle) { | 648 void MetricsService::HandleIdleSinceLastTransmission(bool in_idle) { |
| 667 // If there wasn't a lot of action, maybe the computer was asleep, in which | 649 // If there wasn't a lot of action, maybe the computer was asleep, in which |
| 668 // case, the log transmissions should have stopped. Here we start them up | 650 // case, the log transmissions should have stopped. Here we start them up |
| 669 // again. | 651 // again. |
| 670 if (!in_idle && idle_since_last_transmission_) | 652 if (!in_idle && idle_since_last_transmission_) |
| 671 StartLogTransmissionTimer(); | 653 StartSchedulerIfNecessary(); |
| 672 idle_since_last_transmission_ = in_idle; | 654 idle_since_last_transmission_ = in_idle; |
| 673 } | 655 } |
| 674 | 656 |
| 675 void MetricsService::RecordStartOfSessionEnd() { | 657 void MetricsService::RecordStartOfSessionEnd() { |
| 676 LogCleanShutdown(); | 658 LogCleanShutdown(); |
| 677 RecordBooleanPrefValue(prefs::kStabilitySessionEndCompleted, false); | 659 RecordBooleanPrefValue(prefs::kStabilitySessionEndCompleted, false); |
| 678 } | 660 } |
| 679 | 661 |
| 680 void MetricsService::RecordCompletedSessionEnd() { | 662 void MetricsService::RecordCompletedSessionEnd() { |
| 681 LogCleanShutdown(); | 663 LogCleanShutdown(); |
| 682 RecordBooleanPrefValue(prefs::kStabilitySessionEndCompleted, true); | 664 RecordBooleanPrefValue(prefs::kStabilitySessionEndCompleted, true); |
| 683 } | 665 } |
| 684 | 666 |
| 685 void MetricsService:: RecordBreakpadRegistration(bool success) { | 667 void MetricsService::RecordBreakpadRegistration(bool success) { |
| 686 if (!success) | 668 if (!success) |
| 687 IncrementPrefValue(prefs::kStabilityBreakpadRegistrationFail); | 669 IncrementPrefValue(prefs::kStabilityBreakpadRegistrationFail); |
| 688 else | 670 else |
| 689 IncrementPrefValue(prefs::kStabilityBreakpadRegistrationSuccess); | 671 IncrementPrefValue(prefs::kStabilityBreakpadRegistrationSuccess); |
| 690 } | 672 } |
| 691 | 673 |
| 692 void MetricsService::RecordBreakpadHasDebugger(bool has_debugger) { | 674 void MetricsService::RecordBreakpadHasDebugger(bool has_debugger) { |
| 693 if (!has_debugger) | 675 if (!has_debugger) |
| 694 IncrementPrefValue(prefs::kStabilityDebuggerNotPresent); | 676 IncrementPrefValue(prefs::kStabilityDebuggerNotPresent); |
| 695 else | 677 else |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 850 if (state_ == INITIALIZED) { | 832 if (state_ == INITIALIZED) { |
| 851 // We only need to schedule that run once. | 833 // We only need to schedule that run once. |
| 852 state_ = INIT_TASK_SCHEDULED; | 834 state_ = INIT_TASK_SCHEDULED; |
| 853 | 835 |
| 854 // Schedules a task on the file thread for execution of slower | 836 // Schedules a task on the file thread for execution of slower |
| 855 // initialization steps (such as plugin list generation) necessary | 837 // initialization steps (such as plugin list generation) necessary |
| 856 // for sending the initial log. This avoids blocking the main UI | 838 // for sending the initial log. This avoids blocking the main UI |
| 857 // thread. | 839 // thread. |
| 858 g_browser_process->file_thread()->message_loop()->PostDelayedTask(FROM_HERE, | 840 g_browser_process->file_thread()->message_loop()->PostDelayedTask(FROM_HERE, |
| 859 new InitTask(MessageLoop::current()), | 841 new InitTask(MessageLoop::current()), |
| 860 kInitialInterlogDuration * 1000 / 2); | 842 kInitializationDelaySeconds * 1000); |
| 861 } | 843 } |
| 862 } | 844 } |
| 863 | 845 |
| 864 void MetricsService::StopRecording(MetricsLogBase** log) { | 846 void MetricsService::StopRecording(MetricsLogBase** log) { |
| 865 if (!current_log_) | 847 if (!current_log_) |
| 866 return; | 848 return; |
| 867 | 849 |
| 868 current_log_->set_hardware_class(hardware_class_); // Adds to ongoing logs. | 850 current_log_->set_hardware_class(hardware_class_); // Adds to ongoing logs. |
| 869 | 851 |
| 870 // TODO(jar): Integrate bounds on log recording more consistently, so that we | 852 // TODO(jar): Integrate bounds on log recording more consistently, so that we |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 917 } | 899 } |
| 918 DCHECK(!pending_log()); | 900 DCHECK(!pending_log()); |
| 919 StopRecording(&pending_log_); | 901 StopRecording(&pending_log_); |
| 920 PreparePendingLogText(); | 902 PreparePendingLogText(); |
| 921 PushPendingLogTextToUnsentOngoingLogs(); | 903 PushPendingLogTextToUnsentOngoingLogs(); |
| 922 DiscardPendingLog(); | 904 DiscardPendingLog(); |
| 923 StoreUnsentLogs(); | 905 StoreUnsentLogs(); |
| 924 } | 906 } |
| 925 | 907 |
| 926 void MetricsService::PushPendingLogTextToUnsentOngoingLogs() { | 908 void MetricsService::PushPendingLogTextToUnsentOngoingLogs() { |
| 927 // If UMA response told us not to upload, there's no need to save the pending | |
| 928 // log. It wasn't supposed to be uploaded anyway. | |
| 929 if (!server_permits_upload_) | |
| 930 return; | |
| 931 if (compressed_log_.length() > | 909 if (compressed_log_.length() > |
| 932 static_cast<size_t>(kUploadLogAvoidRetransmitSize)) { | 910 static_cast<size_t>(kUploadLogAvoidRetransmitSize)) { |
| 933 UMA_HISTOGRAM_COUNTS("UMA.Large Accumulated Log Not Persisted", | 911 UMA_HISTOGRAM_COUNTS("UMA.Large Accumulated Log Not Persisted", |
| 934 static_cast<int>(compressed_log_.length())); | 912 static_cast<int>(compressed_log_.length())); |
| 935 return; | 913 return; |
| 936 } | 914 } |
| 937 unsent_ongoing_logs_.push_back(compressed_log_); | 915 unsent_ongoing_logs_.push_back(compressed_log_); |
| 938 } | 916 } |
| 939 | 917 |
| 940 //------------------------------------------------------------------------------ | 918 //------------------------------------------------------------------------------ |
| 941 // Transmission of logs methods | 919 // Transmission of logs methods |
| 942 | 920 |
| 943 void MetricsService::StartLogTransmissionTimer() { | 921 void MetricsService::StartSchedulerIfNecessary() { |
| 944 // If we're not reporting, there's no point in starting a log transmission | 922 if (reporting_active() && recording_active()) |
| 945 // timer. | 923 scheduler_->Start(); |
| 946 if (!reporting_active()) | |
| 947 return; | |
| 948 | |
| 949 if (!current_log_) | |
| 950 return; // Recorder is shutdown. | |
| 951 | |
| 952 // If there is already a timer running, we leave it running. | |
| 953 // If timer_pending is true because the fetch is waiting for a response, | |
| 954 // we return for now and let the response handler start the timer. | |
| 955 if (timer_pending_) | |
| 956 return; | |
| 957 | |
| 958 // Before starting the timer, set timer_pending_ to true. | |
| 959 timer_pending_ = true; | |
| 960 | |
| 961 // Right before the UMA transmission gets started, there's one more thing we'd | |
| 962 // like to record: the histogram of memory usage, so we spawn a task to | |
| 963 // collect the memory details and when that task is finished, it will call | |
| 964 // OnMemoryDetailCollectionDone, which will call HistogramSynchronization to | |
| 965 // collect histograms from all renderers and then we will call | |
| 966 // OnHistogramSynchronizationDone to continue processing. | |
| 967 MessageLoop::current()->PostDelayedTask(FROM_HERE, | |
| 968 log_sender_factory_. | |
| 969 NewRunnableMethod(&MetricsService::LogTransmissionTimerDone), | |
| 970 interlog_duration_.InMilliseconds()); | |
| 971 } | 924 } |
| 972 | 925 |
| 973 void MetricsService::LogTransmissionTimerDone() { | 926 void MetricsService::StartScheduledUpload() { |
| 927 // If reporting has been turned off, the scheduler doesn't need to run. |
| 928 if (!reporting_active() || !recording_active()) { |
| 929 scheduler_->Stop(); |
| 930 scheduler_->UploadCancelled(); |
| 931 return; |
| 932 } |
| 933 |
| 934 DCHECK(!waiting_for_asynchronus_reporting_step_); |
| 935 waiting_for_asynchronus_reporting_step_ = true; |
| 936 |
| 974 Task* task = log_sender_factory_. | 937 Task* task = log_sender_factory_. |
| 975 NewRunnableMethod(&MetricsService::OnMemoryDetailCollectionDone); | 938 NewRunnableMethod(&MetricsService::OnMemoryDetailCollectionDone); |
| 976 | 939 |
| 977 scoped_refptr<MetricsMemoryDetails> details(new MetricsMemoryDetails(task)); | 940 scoped_refptr<MetricsMemoryDetails> details(new MetricsMemoryDetails(task)); |
| 978 details->StartFetch(); | 941 details->StartFetch(); |
| 979 | 942 |
| 980 // Collect WebCore cache information to put into a histogram. | 943 // Collect WebCore cache information to put into a histogram. |
| 981 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); | 944 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); |
| 982 !i.IsAtEnd(); i.Advance()) | 945 !i.IsAtEnd(); i.Advance()) |
| 983 i.GetCurrentValue()->Send(new ViewMsg_GetCacheResourceStats()); | 946 i.GetCurrentValue()->Send(new ViewMsg_GetCacheResourceStats()); |
| 984 } | 947 } |
| 985 | 948 |
| 986 void MetricsService::OnMemoryDetailCollectionDone() { | 949 void MetricsService::OnMemoryDetailCollectionDone() { |
| 987 DCHECK(IsSingleThreaded()); | 950 DCHECK(IsSingleThreaded()); |
| 951 // This function should only be called as the callback from an ansynchronous |
| 952 // step. |
| 953 DCHECK(waiting_for_asynchronus_reporting_step_); |
| 988 | 954 |
| 989 // HistogramSynchronizer will Collect histograms from all renderers and it | 955 // Right before the UMA transmission gets started, there's one more thing we'd |
| 990 // will call OnHistogramSynchronizationDone (if wait time elapses before it | 956 // like to record: the histogram of memory usage, so we spawn a task to |
| 991 // heard from all renderers, then also it will call | 957 // collect the memory details and when that task is finished, it will call |
| 992 // OnHistogramSynchronizationDone). | 958 // OnMemoryDetailCollectionDone, which will call HistogramSynchronization to |
| 959 // collect histograms from all renderers and then we will call |
| 960 // OnHistogramSynchronizationDone to continue processing. |
| 993 | 961 |
| 994 // Create a callback_task for OnHistogramSynchronizationDone. | 962 // Create a callback_task for OnHistogramSynchronizationDone. |
| 995 Task* callback_task = log_sender_factory_.NewRunnableMethod( | 963 Task* callback_task = log_sender_factory_.NewRunnableMethod( |
| 996 &MetricsService::OnHistogramSynchronizationDone); | 964 &MetricsService::OnHistogramSynchronizationDone); |
| 997 | 965 |
| 998 // Set up the callback to task to call after we receive histograms from all | 966 // Set up the callback to task to call after we receive histograms from all |
| 999 // renderer processes. Wait time specifies how long to wait before absolutely | 967 // renderer processes. Wait time specifies how long to wait before absolutely |
| 1000 // calling us back on the task. | 968 // calling us back on the task. |
| 1001 HistogramSynchronizer::FetchRendererHistogramsAsynchronously( | 969 HistogramSynchronizer::FetchRendererHistogramsAsynchronously( |
| 1002 MessageLoop::current(), callback_task, | 970 MessageLoop::current(), callback_task, |
| 1003 kMaxHistogramGatheringWaitDuration); | 971 kMaxHistogramGatheringWaitDuration); |
| 1004 } | 972 } |
| 1005 | 973 |
| 1006 void MetricsService::OnHistogramSynchronizationDone() { | 974 void MetricsService::OnHistogramSynchronizationDone() { |
| 1007 DCHECK(IsSingleThreaded()); | 975 DCHECK(IsSingleThreaded()); |
| 1008 | 976 |
| 1009 // This function should only be called via timer, so timer_pending_ | 977 // If somehow there is a fetch in progress, we return and hope things work |
| 1010 // should be true. | 978 // out. The scheduler isn't informed since if this happens, the scheduler |
| 1011 DCHECK(timer_pending_); | 979 // will get a response from the upload. |
| 1012 timer_pending_ = false; | 980 DCHECK(!current_fetch_.get()); |
| 981 if (current_fetch_.get()) |
| 982 return; |
| 1013 | 983 |
| 1014 DCHECK(!current_fetch_.get()); | 984 // This function should only be called as the callback from an ansynchronous |
| 985 // step. |
| 986 DCHECK(waiting_for_asynchronus_reporting_step_); |
| 987 waiting_for_asynchronus_reporting_step_ = false; |
| 1015 | 988 |
| 1016 // If we're getting no notifications, then the log won't have much in it, and | 989 // If we're getting no notifications, then the log won't have much in it, and |
| 1017 // it's possible the computer is about to go to sleep, so don't upload and | 990 // it's possible the computer is about to go to sleep, so don't upload and |
| 1018 // don't restart the transmission timer. | 991 // stop the scheduler. |
| 1019 if (idle_since_last_transmission_) | 992 // Similarly, if logs should no longer be uploaded, stop here. |
| 1020 return; | 993 if (idle_since_last_transmission_ || |
| 1021 | 994 !recording_active() || !reporting_active()) { |
| 1022 // If somehow there is a fetch in progress, we return setting timer_pending_ | 995 scheduler_->Stop(); |
| 1023 // to true and hope things work out. | 996 scheduler_->UploadCancelled(); |
| 1024 if (current_fetch_.get()) { | |
| 1025 timer_pending_ = true; | |
| 1026 return; | 997 return; |
| 1027 } | 998 } |
| 1028 | 999 |
| 1029 // If uploads are forbidden by UMA response, there's no point in keeping | |
| 1030 // the current_log_, and the more often we delete it, the less likely it is | |
| 1031 // to expand forever. | |
| 1032 if (!server_permits_upload_ && current_log_) { | |
| 1033 StopRecording(NULL); | |
| 1034 StartRecording(); | |
| 1035 } | |
| 1036 | |
| 1037 if (!current_log_) | |
| 1038 return; // Logging was disabled. | |
| 1039 if (!reporting_active()) | |
| 1040 return; // Don't do work if we're not going to send anything now. | |
| 1041 | |
| 1042 MakePendingLog(); | 1000 MakePendingLog(); |
| 1043 | 1001 |
| 1044 // MakePendingLog should have put something in the pending log, if it didn't, | 1002 // MakePendingLog should have put something in the pending log, if it didn't, |
| 1045 // we start the timer again, return and hope things work out. | 1003 // we skip this upload and hope things work out next time. |
| 1046 if (!pending_log()) { | 1004 if (!pending_log()) { |
| 1047 StartLogTransmissionTimer(); | 1005 scheduler_->UploadCancelled(); |
| 1048 return; | 1006 return; |
| 1049 } | 1007 } |
| 1050 | 1008 |
| 1051 // If we're not supposed to upload any UMA data because the response said so, | |
| 1052 // cancel the upload at this point, but start the timer. | |
| 1053 if (!ServerPermitsTransmission()) { | |
| 1054 DiscardPendingLog(); | |
| 1055 StartLogTransmissionTimer(); | |
| 1056 return; | |
| 1057 } | |
| 1058 | |
| 1059 PrepareFetchWithPendingLog(); | 1009 PrepareFetchWithPendingLog(); |
| 1060 | 1010 |
| 1061 if (!current_fetch_.get()) { | 1011 if (!current_fetch_.get()) { |
| 1062 // Compression failed, and log discarded :-/. | 1012 // Compression failed, and log discarded :-/. |
| 1063 DiscardPendingLog(); | 1013 DiscardPendingLog(); |
| 1064 StartLogTransmissionTimer(); // Maybe we'll do better next time | 1014 scheduler_->UploadCancelled(); |
| 1065 // TODO(jar): If compression failed, we should have created a tiny log and | 1015 // TODO(jar): If compression failed, we should have created a tiny log and |
| 1066 // compressed that, so that we can signal that we're losing logs. | 1016 // compressed that, so that we can signal that we're losing logs. |
| 1067 return; | 1017 return; |
| 1068 } | 1018 } |
| 1069 | 1019 |
| 1070 DCHECK(!timer_pending_); | 1020 DCHECK(!waiting_for_asynchronus_reporting_step_); |
| 1071 | 1021 |
| 1072 // The URL fetch is a like timer in that after a while we get called back | 1022 waiting_for_asynchronus_reporting_step_ = true; |
| 1073 // so we set timer_pending_ true just as we start the url fetch. | |
| 1074 timer_pending_ = true; | |
| 1075 current_fetch_->Start(); | 1023 current_fetch_->Start(); |
| 1076 | 1024 |
| 1077 HandleIdleSinceLastTransmission(true); | 1025 HandleIdleSinceLastTransmission(true); |
| 1078 } | 1026 } |
| 1079 | 1027 |
| 1080 | 1028 |
| 1081 void MetricsService::MakePendingLog() { | 1029 void MetricsService::MakePendingLog() { |
| 1082 if (pending_log()) | 1030 if (pending_log()) |
| 1083 return; | 1031 return; |
| 1084 | 1032 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1120 break; | 1068 break; |
| 1121 | 1069 |
| 1122 default: | 1070 default: |
| 1123 NOTREACHED(); | 1071 NOTREACHED(); |
| 1124 return; | 1072 return; |
| 1125 } | 1073 } |
| 1126 | 1074 |
| 1127 DCHECK(pending_log()); | 1075 DCHECK(pending_log()); |
| 1128 } | 1076 } |
| 1129 | 1077 |
| 1130 bool MetricsService::ServerPermitsTransmission() const { | |
| 1131 // If the server forbids uploading, we take that to mean it forbids current | |
| 1132 // logs, but we still send up the inital logs and any old logs. | |
| 1133 if (server_permits_upload_) | |
| 1134 return true; | |
| 1135 | |
| 1136 switch (state_) { | |
| 1137 case INITIAL_LOG_READY: | |
| 1138 case SEND_OLD_INITIAL_LOGS: | |
| 1139 case SENDING_OLD_LOGS: | |
| 1140 return true; | |
| 1141 | |
| 1142 case SENDING_CURRENT_LOGS: | |
| 1143 default: | |
| 1144 return false; | |
| 1145 } | |
| 1146 } | |
| 1147 | |
| 1148 void MetricsService::PrepareInitialLog() { | 1078 void MetricsService::PrepareInitialLog() { |
| 1149 DCHECK(state_ == INIT_TASK_DONE); | 1079 DCHECK(state_ == INIT_TASK_DONE); |
| 1150 | 1080 |
| 1151 MetricsLog* log = new MetricsLog(client_id_, session_id_); | 1081 MetricsLog* log = new MetricsLog(client_id_, session_id_); |
| 1152 log->set_hardware_class(hardware_class_); // Adds to initial log. | 1082 log->set_hardware_class(hardware_class_); // Adds to initial log. |
| 1153 log->RecordEnvironment(plugins_, profile_dictionary_.get()); | 1083 log->RecordEnvironment(plugins_, profile_dictionary_.get()); |
| 1154 | 1084 |
| 1155 // Histograms only get written to current_log_, so setup for the write. | 1085 // Histograms only get written to current_log_, so setup for the write. |
| 1156 MetricsLogBase* save_log = current_log_; | 1086 MetricsLogBase* save_log = current_log_; |
| 1157 current_log_ = log; | 1087 current_log_ = log; |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1356 return "Unknown"; | 1286 return "Unknown"; |
| 1357 } | 1287 } |
| 1358 } | 1288 } |
| 1359 | 1289 |
| 1360 void MetricsService::OnURLFetchComplete(const URLFetcher* source, | 1290 void MetricsService::OnURLFetchComplete(const URLFetcher* source, |
| 1361 const GURL& url, | 1291 const GURL& url, |
| 1362 const net::URLRequestStatus& status, | 1292 const net::URLRequestStatus& status, |
| 1363 int response_code, | 1293 int response_code, |
| 1364 const ResponseCookies& cookies, | 1294 const ResponseCookies& cookies, |
| 1365 const std::string& data) { | 1295 const std::string& data) { |
| 1366 DCHECK(timer_pending_); | 1296 DCHECK(waiting_for_asynchronus_reporting_step_); |
| 1367 timer_pending_ = false; | 1297 waiting_for_asynchronus_reporting_step_ = false; |
| 1368 DCHECK(current_fetch_.get()); | 1298 DCHECK(current_fetch_.get()); |
| 1369 current_fetch_.reset(NULL); // We're not allowed to re-use it. | 1299 current_fetch_.reset(NULL); // We're not allowed to re-use it. |
| 1370 | 1300 |
| 1371 // Confirm send so that we can move on. | 1301 // Confirm send so that we can move on. |
| 1372 VLOG(1) << "METRICS RESPONSE CODE: " << response_code | 1302 VLOG(1) << "METRICS RESPONSE CODE: " << response_code |
| 1373 << " status=" << StatusToString(status); | 1303 << " status=" << StatusToString(status); |
| 1374 | 1304 |
| 1305 bool upload_succeeded = response_code == 200; |
| 1306 |
| 1375 // Provide boolean for error recovery (allow us to ignore response_code). | 1307 // Provide boolean for error recovery (allow us to ignore response_code). |
| 1376 bool discard_log = false; | 1308 bool discard_log = false; |
| 1377 | 1309 |
| 1378 if (response_code != 200 && | 1310 if (!upload_succeeded && |
| 1379 (compressed_log_.length() > | 1311 (compressed_log_.length() > |
| 1380 static_cast<size_t>(kUploadLogAvoidRetransmitSize))) { | 1312 static_cast<size_t>(kUploadLogAvoidRetransmitSize))) { |
| 1381 UMA_HISTOGRAM_COUNTS("UMA.Large Rejected Log was Discarded", | 1313 UMA_HISTOGRAM_COUNTS("UMA.Large Rejected Log was Discarded", |
| 1382 static_cast<int>(compressed_log_.length())); | 1314 static_cast<int>(compressed_log_.length())); |
| 1383 discard_log = true; | 1315 discard_log = true; |
| 1384 } else if (response_code == 400) { | 1316 } else if (response_code == 400) { |
| 1385 // Bad syntax. Retransmission won't work. | 1317 // Bad syntax. Retransmission won't work. |
| 1386 UMA_HISTOGRAM_COUNTS("UMA.Unacceptable_Log_Discarded", state_); | 1318 UMA_HISTOGRAM_COUNTS("UMA.Unacceptable_Log_Discarded", state_); |
| 1387 discard_log = true; | 1319 discard_log = true; |
| 1388 } | 1320 } |
| 1389 | 1321 |
| 1390 if (response_code != 200 && !discard_log) { | 1322 if (!upload_succeeded && !discard_log) { |
| 1391 VLOG(1) << "METRICS: transmission attempt returned a failure code: " | 1323 VLOG(1) << "METRICS: transmission attempt returned a failure code: " |
| 1392 << response_code << ". Verify network connectivity"; | 1324 << response_code << ". Verify network connectivity"; |
| 1393 HandleBadResponseCode(); | 1325 LogBadResponseCode(); |
| 1394 } else { // Successful receipt (or we are discarding log). | 1326 } else { // Successful receipt (or we are discarding log). |
| 1395 VLOG(1) << "METRICS RESPONSE DATA: " << data; | 1327 VLOG(1) << "METRICS RESPONSE DATA: " << data; |
| 1396 switch (state_) { | 1328 switch (state_) { |
| 1397 case INITIAL_LOG_READY: | 1329 case INITIAL_LOG_READY: |
| 1398 state_ = SEND_OLD_INITIAL_LOGS; | 1330 state_ = SEND_OLD_INITIAL_LOGS; |
| 1399 break; | 1331 break; |
| 1400 | 1332 |
| 1401 case SEND_OLD_INITIAL_LOGS: | 1333 case SEND_OLD_INITIAL_LOGS: |
| 1402 DCHECK(!unsent_initial_logs_.empty()); | 1334 DCHECK(!unsent_initial_logs_.empty()); |
| 1403 unsent_initial_logs_.pop_back(); | 1335 unsent_initial_logs_.pop_back(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1418 break; | 1350 break; |
| 1419 } | 1351 } |
| 1420 | 1352 |
| 1421 DiscardPendingLog(); | 1353 DiscardPendingLog(); |
| 1422 // Since we sent a log, make sure our in-memory state is recorded to disk. | 1354 // Since we sent a log, make sure our in-memory state is recorded to disk. |
| 1423 PrefService* local_state = g_browser_process->local_state(); | 1355 PrefService* local_state = g_browser_process->local_state(); |
| 1424 DCHECK(local_state); | 1356 DCHECK(local_state); |
| 1425 if (local_state) | 1357 if (local_state) |
| 1426 local_state->ScheduleSavePersistentPrefs(); | 1358 local_state->ScheduleSavePersistentPrefs(); |
| 1427 | 1359 |
| 1428 // Override usual interlog delay if there are unsent logs to transmit, | 1360 if (unsent_logs()) |
| 1429 // otherwise reset back to default. | |
| 1430 if (unsent_logs()) { | |
| 1431 DCHECK(state_ < SENDING_CURRENT_LOGS); | 1361 DCHECK(state_ < SENDING_CURRENT_LOGS); |
| 1432 interlog_duration_ = TimeDelta::FromSeconds(kUnsentLogDelay); | |
| 1433 } else { | |
| 1434 interlog_duration_ = TimeDelta::FromSeconds(kMinSecondsPerLog); | |
| 1435 } | |
| 1436 } | 1362 } |
| 1437 | 1363 |
| 1438 StartLogTransmissionTimer(); | 1364 // Error 400 indicates a problem with the log, not with the server, so |
| 1365 // don't consider that a sign that the server is in trouble. |
| 1366 bool server_is_healthy = upload_succeeded || response_code == 400; |
| 1367 |
| 1368 scheduler_->UploadFinished(server_is_healthy, unsent_logs()); |
| 1439 } | 1369 } |
| 1440 | 1370 |
| 1441 void MetricsService::HandleBadResponseCode() { | 1371 void MetricsService::LogBadResponseCode() { |
| 1442 VLOG(1) << "Verify your metrics logs are formatted correctly. Verify server " | 1372 VLOG(1) << "Verify your metrics logs are formatted correctly. Verify server " |
| 1443 "is active at " << server_url_; | 1373 "is active at " << server_url_; |
| 1444 if (!pending_log()) { | 1374 if (!pending_log()) { |
| 1445 VLOG(1) << "METRICS: Recorder shutdown during log transmission."; | 1375 VLOG(1) << "METRICS: Recorder shutdown during log transmission."; |
| 1446 } else { | 1376 } else { |
| 1447 // Send progressively less frequently. | 1377 VLOG(1) << "METRICS: transmission retry being scheduled for " |
| 1448 DCHECK(kBackoff > 1.0); | |
| 1449 interlog_duration_ = TimeDelta::FromMicroseconds( | |
| 1450 static_cast<int64>(kBackoff * interlog_duration_.InMicroseconds())); | |
| 1451 | |
| 1452 if (kMaxBackoff * TimeDelta::FromSeconds(kMinSecondsPerLog) < | |
| 1453 interlog_duration_) { | |
| 1454 interlog_duration_ = kMaxBackoff * | |
| 1455 TimeDelta::FromSeconds(kMinSecondsPerLog); | |
| 1456 } | |
| 1457 | |
| 1458 VLOG(1) << "METRICS: transmission retry being scheduled in " | |
| 1459 << interlog_duration_.InSeconds() << " seconds for " | |
| 1460 << compressed_log_; | 1378 << compressed_log_; |
| 1461 } | 1379 } |
| 1462 } | 1380 } |
| 1463 | 1381 |
| 1464 void MetricsService::LogWindowChange(NotificationType type, | 1382 void MetricsService::LogWindowChange(NotificationType type, |
| 1465 const NotificationSource& source, | 1383 const NotificationSource& source, |
| 1466 const NotificationDetails& details) { | 1384 const NotificationDetails& details) { |
| 1467 int controller_id = -1; | 1385 int controller_id = -1; |
| 1468 uintptr_t window_or_tab = source.map_key(); | 1386 uintptr_t window_or_tab = source.map_key(); |
| 1469 MetricsLog::WindowEventType window_type; | 1387 MetricsLog::WindowEventType window_type; |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1767 thread_id = base::PlatformThread::CurrentId(); | 1685 thread_id = base::PlatformThread::CurrentId(); |
| 1768 return base::PlatformThread::CurrentId() == thread_id; | 1686 return base::PlatformThread::CurrentId() == thread_id; |
| 1769 } | 1687 } |
| 1770 | 1688 |
| 1771 #if defined(OS_CHROMEOS) | 1689 #if defined(OS_CHROMEOS) |
| 1772 void MetricsService::StartExternalMetrics() { | 1690 void MetricsService::StartExternalMetrics() { |
| 1773 external_metrics_ = new chromeos::ExternalMetrics; | 1691 external_metrics_ = new chromeos::ExternalMetrics; |
| 1774 external_metrics_->Start(); | 1692 external_metrics_->Start(); |
| 1775 } | 1693 } |
| 1776 #endif | 1694 #endif |
| OLD | NEW |