Chromium Code Reviews| 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 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 163 #include "base/string_number_conversions.h" | 163 #include "base/string_number_conversions.h" |
| 164 #include "base/threading/platform_thread.h" | 164 #include "base/threading/platform_thread.h" |
| 165 #include "base/threading/thread.h" | 165 #include "base/threading/thread.h" |
| 166 #include "base/utf_string_conversions.h" | 166 #include "base/utf_string_conversions.h" |
| 167 #include "base/values.h" | 167 #include "base/values.h" |
| 168 #include "chrome/browser/bookmarks/bookmark_model.h" | 168 #include "chrome/browser/bookmarks/bookmark_model.h" |
| 169 #include "chrome/browser/browser_process.h" | 169 #include "chrome/browser/browser_process.h" |
| 170 #include "chrome/browser/load_notification_details.h" | 170 #include "chrome/browser/load_notification_details.h" |
| 171 #include "chrome/browser/metrics/histogram_synchronizer.h" | 171 #include "chrome/browser/metrics/histogram_synchronizer.h" |
| 172 #include "chrome/browser/metrics/metrics_log.h" | 172 #include "chrome/browser/metrics/metrics_log.h" |
| 173 #include "chrome/browser/metrics/metrics_reporting_scheduler.h" | |
| 173 #include "chrome/browser/prefs/pref_service.h" | 174 #include "chrome/browser/prefs/pref_service.h" |
| 174 #include "chrome/browser/prefs/scoped_user_pref_update.h" | 175 #include "chrome/browser/prefs/scoped_user_pref_update.h" |
| 175 #include "chrome/browser/profiles/profile.h" | 176 #include "chrome/browser/profiles/profile.h" |
| 176 #include "chrome/browser/search_engines/template_url_model.h" | 177 #include "chrome/browser/search_engines/template_url_model.h" |
| 177 #include "chrome/browser/ui/browser_list.h" | 178 #include "chrome/browser/ui/browser_list.h" |
| 178 #include "chrome/common/child_process_logging.h" | 179 #include "chrome/common/child_process_logging.h" |
| 179 #include "chrome/common/chrome_switches.h" | 180 #include "chrome/common/chrome_switches.h" |
| 180 #include "chrome/common/guid.h" | 181 #include "chrome/common/guid.h" |
| 181 #include "chrome/common/pref_names.h" | 182 #include "chrome/common/pref_names.h" |
| 182 #include "chrome/common/render_messages.h" | 183 #include "chrome/common/render_messages.h" |
| 183 #include "content/browser/renderer_host/render_process_host.h" | 184 #include "content/browser/renderer_host/render_process_host.h" |
| 184 #include "content/common/child_process_info.h" | 185 #include "content/common/child_process_info.h" |
| 185 #include "content/common/notification_service.h" | 186 #include "content/common/notification_service.h" |
| 186 #include "libxml/xmlwriter.h" | |
| 187 #include "webkit/plugins/npapi/plugin_list.h" | 187 #include "webkit/plugins/npapi/plugin_list.h" |
| 188 #include "webkit/plugins/npapi/webplugininfo.h" | 188 #include "webkit/plugins/npapi/webplugininfo.h" |
| 189 | 189 |
| 190 // TODO(port): port browser_distribution.h. | 190 // TODO(port): port browser_distribution.h. |
| 191 #if !defined(OS_POSIX) | 191 #if !defined(OS_POSIX) |
| 192 #include "chrome/installer/util/browser_distribution.h" | 192 #include "chrome/installer/util/browser_distribution.h" |
| 193 #endif | 193 #endif |
| 194 | 194 |
| 195 #if defined(OS_CHROMEOS) | 195 #if defined(OS_CHROMEOS) |
| 196 #include "chrome/browser/chromeos/cros/cros_library.h" | 196 #include "chrome/browser/chromeos/cros/cros_library.h" |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 207 } | 207 } |
| 208 | 208 |
| 209 // TODO(ziadh): Remove this when done with experiment. | 209 // TODO(ziadh): Remove this when done with experiment. |
| 210 void MakeStoreStatusHistogram(MetricsService::LogStoreStatus status) { | 210 void MakeStoreStatusHistogram(MetricsService::LogStoreStatus status) { |
| 211 UMA_HISTOGRAM_ENUMERATION("PrefService.PersistentLogStore2", status, | 211 UMA_HISTOGRAM_ENUMERATION("PrefService.PersistentLogStore2", status, |
| 212 MetricsService::END_STORE_STATUS); | 212 MetricsService::END_STORE_STATUS); |
| 213 } | 213 } |
| 214 } // namespace | 214 } // namespace |
| 215 | 215 |
| 216 using base::Time; | 216 using base::Time; |
| 217 using base::TimeDelta; | |
| 218 | 217 |
| 219 // Check to see that we're being called on only one thread. | 218 // Check to see that we're being called on only one thread. |
| 220 static bool IsSingleThreaded(); | 219 static bool IsSingleThreaded(); |
| 221 | 220 |
| 222 static const char kMetricsType[] = "application/vnd.mozilla.metrics.bz2"; | 221 static const char kMetricsType[] = "application/vnd.mozilla.metrics.bz2"; |
| 223 | 222 |
| 224 // The delay, in seconds, after startup before sending the first log message. | 223 // The delay, in seconds, after starting recording before doing expensive |
| 225 static const int kInitialInterlogDuration = 60; // one minute | 224 // initialization work. |
| 225 static const int kInitializationDelaySeconds = 30; | |
| 226 | 226 |
| 227 // This specifies the amount of time to wait for all renderers to send their | 227 // This specifies the amount of time to wait for all renderers to send their |
| 228 // data. | 228 // data. |
| 229 static const int kMaxHistogramGatheringWaitDuration = 60000; // 60 seconds. | 229 static const int kMaxHistogramGatheringWaitDuration = 60000; // 60 seconds. |
| 230 | 230 |
| 231 // The maximum number of events in a log uploaded to the UMA server. | 231 // The maximum number of events in a log uploaded to the UMA server. |
| 232 static const int kEventLimit = 2400; | 232 static const int kEventLimit = 2400; |
| 233 | 233 |
| 234 // If an upload fails, and the transmission was over this byte count, then we | 234 // If an upload fails, and the transmission was over this byte count, then we |
| 235 // will discard the log, and not try to retransmit it. We also don't persist | 235 // will discard the log, and not try to retransmit it. We also don't persist |
| 236 // the log to the prefs for transmission during the next chrome session if this | 236 // the log to the prefs for transmission during the next chrome session if this |
| 237 // limit is exceeded. | 237 // limit is exceeded. |
| 238 static const int kUploadLogAvoidRetransmitSize = 50000; | 238 static const int kUploadLogAvoidRetransmitSize = 50000; |
| 239 | 239 |
| 240 // When we have logs from previous Chrome sessions to send, how long should we | |
| 241 // delay (in seconds) between each log transmission. | |
| 242 static const int kUnsentLogDelay = 15; // 15 seconds | |
| 243 | |
| 244 // Minimum time a log typically exists before sending, in seconds. | |
| 245 // This number is supplied by the server, but until we parse it out of a server | |
| 246 // response, we use this duration to specify how long we should wait before | |
| 247 // sending the next log. If the channel is busy, such as when there is a | |
| 248 // failure during an attempt to transmit a previous log, then a log may wait | |
| 249 // (and continue to accrue new log entries) for a much greater period of time. | |
| 250 static const int kMinSecondsPerLog = 30 * 60; // Thirty minutes. | |
| 251 | |
| 252 // When we don't succeed at transmitting a log to a server, we progressively | |
| 253 // wait longer and longer before sending the next log. This backoff process | |
| 254 // help reduce load on the server, and makes the amount of backoff vary between | |
| 255 // clients so that a collision (server overload?) on retransmit is less likely. | |
| 256 // The following is the constant we use to expand that inter-log duration. | |
| 257 static const double kBackoff = 1.1; | |
| 258 // We limit the maximum backoff to be no greater than some multiple of the | |
| 259 // default kMinSecondsPerLog. The following is that maximum ratio. | |
| 260 static const int kMaxBackoff = 10; | |
| 261 | |
| 262 // Interval, in seconds, between state saves. | 240 // Interval, in seconds, between state saves. |
| 263 static const int kSaveStateInterval = 5 * 60; // five minutes | 241 static const int kSaveStateInterval = 5 * 60; // five minutes |
| 264 | 242 |
| 265 // The number of "initial" logs we're willing to save, and hope to send during | 243 // The number of "initial" logs we're willing to save, and hope to send during |
| 266 // a future Chrome session. Initial logs contain crash stats, and are pretty | 244 // a future Chrome session. Initial logs contain crash stats, and are pretty |
| 267 // small. | 245 // small. |
| 268 static const size_t kMaxInitialLogsPersisted = 20; | 246 static const size_t kMaxInitialLogsPersisted = 20; |
| 269 | 247 |
| 270 // The number of ongoing logs we're willing to save persistently, and hope to | 248 // The number of ongoing logs we're willing to save persistently, and hope to |
| 271 // send during a this or future sessions. Note that each log may be pretty | 249 // send during a this or future sessions. Note that each log may be pretty |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 430 | 408 |
| 431 local_state->ClearPref(prefs::kStabilityPluginStats); | 409 local_state->ClearPref(prefs::kStabilityPluginStats); |
| 432 | 410 |
| 433 local_state->ClearPref(prefs::kMetricsInitialLogs); | 411 local_state->ClearPref(prefs::kMetricsInitialLogs); |
| 434 local_state->ClearPref(prefs::kMetricsOngoingLogs); | 412 local_state->ClearPref(prefs::kMetricsOngoingLogs); |
| 435 } | 413 } |
| 436 | 414 |
| 437 MetricsService::MetricsService() | 415 MetricsService::MetricsService() |
| 438 : recording_active_(false), | 416 : recording_active_(false), |
| 439 reporting_active_(false), | 417 reporting_active_(false), |
| 440 server_permits_upload_(true), | |
| 441 state_(INITIALIZED), | 418 state_(INITIALIZED), |
| 442 current_fetch_(NULL), | 419 current_fetch_(NULL), |
| 443 idle_since_last_transmission_(false), | 420 idle_since_last_transmission_(false), |
| 444 next_window_id_(0), | 421 next_window_id_(0), |
| 445 ALLOW_THIS_IN_INITIALIZER_LIST(log_sender_factory_(this)), | 422 ALLOW_THIS_IN_INITIALIZER_LIST(log_sender_factory_(this)), |
| 446 ALLOW_THIS_IN_INITIALIZER_LIST(state_saver_factory_(this)), | 423 ALLOW_THIS_IN_INITIALIZER_LIST(state_saver_factory_(this)), |
| 447 interlog_duration_(TimeDelta::FromSeconds(kInitialInterlogDuration)), | 424 ALLOW_THIS_IN_INITIALIZER_LIST(scheduler_( |
| 448 timer_pending_(false) { | 425 new MetricsReportingScheduler(this))), |
| 426 waiting_for_asynchronus_reporting_step_(false) { | |
| 449 DCHECK(IsSingleThreaded()); | 427 DCHECK(IsSingleThreaded()); |
| 450 InitializeMetricsState(); | 428 InitializeMetricsState(); |
| 451 } | 429 } |
| 452 | 430 |
| 453 MetricsService::~MetricsService() { | 431 MetricsService::~MetricsService() { |
| 454 SetRecording(false); | 432 SetRecording(false); |
| 455 } | 433 } |
| 456 | 434 |
| 457 void MetricsService::Start() { | 435 void MetricsService::Start() { |
| 458 HandleIdleSinceLastTransmission(false); | 436 HandleIdleSinceLastTransmission(false); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 507 | 485 |
| 508 bool MetricsService::recording_active() const { | 486 bool MetricsService::recording_active() const { |
| 509 DCHECK(IsSingleThreaded()); | 487 DCHECK(IsSingleThreaded()); |
| 510 return recording_active_; | 488 return recording_active_; |
| 511 } | 489 } |
| 512 | 490 |
| 513 void MetricsService::SetReporting(bool enable) { | 491 void MetricsService::SetReporting(bool enable) { |
| 514 if (reporting_active_ != enable) { | 492 if (reporting_active_ != enable) { |
| 515 reporting_active_ = enable; | 493 reporting_active_ = enable; |
| 516 if (reporting_active_) | 494 if (reporting_active_) |
| 517 StartLogTransmissionTimer(); | 495 scheduler_->Start(); |
| 518 } | 496 } |
| 519 } | 497 } |
| 520 | 498 |
| 521 bool MetricsService::reporting_active() const { | 499 bool MetricsService::reporting_active() const { |
| 522 DCHECK(IsSingleThreaded()); | 500 DCHECK(IsSingleThreaded()); |
| 523 return reporting_active_; | 501 return reporting_active_; |
| 524 } | 502 } |
| 525 | 503 |
| 526 // static | 504 // static |
| 527 void MetricsService::SetUpNotifications(NotificationRegistrar* registrar, | 505 void MetricsService::SetUpNotifications(NotificationRegistrar* registrar, |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 643 | 621 |
| 644 if (current_log_) | 622 if (current_log_) |
| 645 DVLOG(1) << "METRICS: NUMBER OF EVENTS = " << current_log_->num_events(); | 623 DVLOG(1) << "METRICS: NUMBER OF EVENTS = " << current_log_->num_events(); |
| 646 } | 624 } |
| 647 | 625 |
| 648 void MetricsService::HandleIdleSinceLastTransmission(bool in_idle) { | 626 void MetricsService::HandleIdleSinceLastTransmission(bool in_idle) { |
| 649 // If there wasn't a lot of action, maybe the computer was asleep, in which | 627 // If there wasn't a lot of action, maybe the computer was asleep, in which |
| 650 // case, the log transmissions should have stopped. Here we start them up | 628 // case, the log transmissions should have stopped. Here we start them up |
| 651 // again. | 629 // again. |
| 652 if (!in_idle && idle_since_last_transmission_) | 630 if (!in_idle && idle_since_last_transmission_) |
| 653 StartLogTransmissionTimer(); | 631 scheduler_->Start(); |
| 654 idle_since_last_transmission_ = in_idle; | 632 idle_since_last_transmission_ = in_idle; |
| 655 } | 633 } |
| 656 | 634 |
| 657 void MetricsService::RecordStartOfSessionEnd() { | 635 void MetricsService::RecordStartOfSessionEnd() { |
| 658 LogCleanShutdown(); | 636 LogCleanShutdown(); |
| 659 RecordBooleanPrefValue(prefs::kStabilitySessionEndCompleted, false); | 637 RecordBooleanPrefValue(prefs::kStabilitySessionEndCompleted, false); |
| 660 } | 638 } |
| 661 | 639 |
| 662 void MetricsService::RecordCompletedSessionEnd() { | 640 void MetricsService::RecordCompletedSessionEnd() { |
| 663 LogCleanShutdown(); | 641 LogCleanShutdown(); |
| 664 RecordBooleanPrefValue(prefs::kStabilitySessionEndCompleted, true); | 642 RecordBooleanPrefValue(prefs::kStabilitySessionEndCompleted, true); |
| 665 } | 643 } |
| 666 | 644 |
| 667 void MetricsService:: RecordBreakpadRegistration(bool success) { | 645 void MetricsService::RecordBreakpadRegistration(bool success) { |
| 668 if (!success) | 646 if (!success) |
| 669 IncrementPrefValue(prefs::kStabilityBreakpadRegistrationFail); | 647 IncrementPrefValue(prefs::kStabilityBreakpadRegistrationFail); |
| 670 else | 648 else |
| 671 IncrementPrefValue(prefs::kStabilityBreakpadRegistrationSuccess); | 649 IncrementPrefValue(prefs::kStabilityBreakpadRegistrationSuccess); |
| 672 } | 650 } |
| 673 | 651 |
| 674 void MetricsService::RecordBreakpadHasDebugger(bool has_debugger) { | 652 void MetricsService::RecordBreakpadHasDebugger(bool has_debugger) { |
| 675 if (!has_debugger) | 653 if (!has_debugger) |
| 676 IncrementPrefValue(prefs::kStabilityDebuggerNotPresent); | 654 IncrementPrefValue(prefs::kStabilityDebuggerNotPresent); |
| 677 else | 655 else |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 832 if (state_ == INITIALIZED) { | 810 if (state_ == INITIALIZED) { |
| 833 // We only need to schedule that run once. | 811 // We only need to schedule that run once. |
| 834 state_ = INIT_TASK_SCHEDULED; | 812 state_ = INIT_TASK_SCHEDULED; |
| 835 | 813 |
| 836 // Schedules a task on the file thread for execution of slower | 814 // Schedules a task on the file thread for execution of slower |
| 837 // initialization steps (such as plugin list generation) necessary | 815 // initialization steps (such as plugin list generation) necessary |
| 838 // for sending the initial log. This avoids blocking the main UI | 816 // for sending the initial log. This avoids blocking the main UI |
| 839 // thread. | 817 // thread. |
| 840 g_browser_process->file_thread()->message_loop()->PostDelayedTask(FROM_HERE, | 818 g_browser_process->file_thread()->message_loop()->PostDelayedTask(FROM_HERE, |
| 841 new InitTask(MessageLoop::current()), | 819 new InitTask(MessageLoop::current()), |
| 842 kInitialInterlogDuration * 1000 / 2); | 820 kInitializationDelaySeconds * 1000); |
| 843 } | 821 } |
| 844 } | 822 } |
| 845 | 823 |
| 846 void MetricsService::StopRecording(MetricsLogBase** log) { | 824 void MetricsService::StopRecording(MetricsLogBase** log) { |
| 847 if (!current_log_) | 825 if (!current_log_) |
| 848 return; | 826 return; |
| 849 | 827 |
| 850 current_log_->set_hardware_class(hardware_class_); // Adds to ongoing logs. | 828 current_log_->set_hardware_class(hardware_class_); // Adds to ongoing logs. |
| 851 | 829 |
| 852 // TODO(jar): Integrate bounds on log recording more consistently, so that we | 830 // 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... | |
| 899 } | 877 } |
| 900 DCHECK(!pending_log()); | 878 DCHECK(!pending_log()); |
| 901 StopRecording(&pending_log_); | 879 StopRecording(&pending_log_); |
| 902 PreparePendingLogText(); | 880 PreparePendingLogText(); |
| 903 PushPendingLogTextToUnsentOngoingLogs(); | 881 PushPendingLogTextToUnsentOngoingLogs(); |
| 904 DiscardPendingLog(); | 882 DiscardPendingLog(); |
| 905 StoreUnsentLogs(); | 883 StoreUnsentLogs(); |
| 906 } | 884 } |
| 907 | 885 |
| 908 void MetricsService::PushPendingLogTextToUnsentOngoingLogs() { | 886 void MetricsService::PushPendingLogTextToUnsentOngoingLogs() { |
| 909 // If UMA response told us not to upload, there's no need to save the pending | |
| 910 // log. It wasn't supposed to be uploaded anyway. | |
| 911 if (!server_permits_upload_) | |
| 912 return; | |
| 913 if (compressed_log_.length() > | 887 if (compressed_log_.length() > |
| 914 static_cast<size_t>(kUploadLogAvoidRetransmitSize)) { | 888 static_cast<size_t>(kUploadLogAvoidRetransmitSize)) { |
| 915 UMA_HISTOGRAM_COUNTS("UMA.Large Accumulated Log Not Persisted", | 889 UMA_HISTOGRAM_COUNTS("UMA.Large Accumulated Log Not Persisted", |
| 916 static_cast<int>(compressed_log_.length())); | 890 static_cast<int>(compressed_log_.length())); |
| 917 return; | 891 return; |
| 918 } | 892 } |
| 919 unsent_ongoing_logs_.push_back(compressed_log_); | 893 unsent_ongoing_logs_.push_back(compressed_log_); |
| 920 } | 894 } |
| 921 | 895 |
| 922 //------------------------------------------------------------------------------ | 896 //------------------------------------------------------------------------------ |
| 923 // Transmission of logs methods | 897 // Transmission of logs methods |
| 924 | 898 |
| 925 void MetricsService::StartLogTransmissionTimer() { | 899 void MetricsService::StartScheduledUpload() { |
| 926 // If we're not reporting, there's no point in starting a log transmission | 900 DCHECK(IsSingleThreaded()); |
| 927 // timer. | |
| 928 if (!reporting_active()) | |
| 929 return; | |
| 930 | 901 |
| 931 if (!current_log_) | 902 waiting_for_asynchronus_reporting_step_ = true; |
|
jar (doing other things)
2011/04/16 02:03:13
If this is part of the timer scheduling, it should
stuartmorgan
2011/04/18 17:03:00
It's not, it's for debugging (see my response to y
| |
| 932 return; // Recorder is shutdown. | |
| 933 | |
| 934 // If there is already a timer running, we leave it running. | |
| 935 // If timer_pending is true because the fetch is waiting for a response, | |
| 936 // we return for now and let the response handler start the timer. | |
| 937 if (timer_pending_) | |
| 938 return; | |
| 939 | |
| 940 // Before starting the timer, set timer_pending_ to true. | |
| 941 timer_pending_ = true; | |
| 942 | 903 |
| 943 // Right before the UMA transmission gets started, there's one more thing we'd | 904 // Right before the UMA transmission gets started, there's one more thing we'd |
| 944 // like to record: the histogram of memory usage, so we spawn a task to | 905 // like to record: the histogram of memory usage, so we spawn a task to |
| 945 // collect histograms from all the renderers and when that task is finished, | 906 // collect histograms from all the renderers. When finished (or if wait time |
| 946 // it will call OnHistogramSynchronizationDone to continue processing. | 907 // elapses before it hears from all renderers), it will call |
| 947 MessageLoop::current()->PostDelayedTask(FROM_HERE, | 908 // OnHistogramSynchronizationDone. |
| 948 log_sender_factory_. | |
| 949 NewRunnableMethod(&MetricsService::LogTransmissionTimerDone), | |
| 950 interlog_duration_.InMilliseconds()); | |
| 951 } | |
| 952 | |
| 953 void MetricsService::LogTransmissionTimerDone() { | |
| 954 DCHECK(IsSingleThreaded()); | |
| 955 | |
| 956 // HistogramSynchronizer will Collect histograms from all renderers and it | |
| 957 // will call OnHistogramSynchronizationDone (if wait time elapses before it | |
| 958 // heard from all renderers, then also it will call | |
| 959 // OnHistogramSynchronizationDone). | |
| 960 | 909 |
| 961 // Create a callback_task for OnHistogramSynchronizationDone. | 910 // Create a callback_task for OnHistogramSynchronizationDone. |
| 962 Task* callback_task = log_sender_factory_.NewRunnableMethod( | 911 Task* callback_task = log_sender_factory_.NewRunnableMethod( |
| 963 &MetricsService::OnHistogramSynchronizationDone); | 912 &MetricsService::OnHistogramSynchronizationDone); |
| 964 | 913 |
| 965 // Set up the callback to task to call after we receive histograms from all | 914 // Set up the callback to task to call after we receive histograms from all |
| 966 // renderer processes. Wait time specifies how long to wait before absolutely | 915 // renderer processes. Wait time specifies how long to wait before absolutely |
| 967 // calling us back on the task. | 916 // calling us back on the task. |
| 968 HistogramSynchronizer::FetchRendererHistogramsAsynchronously( | 917 HistogramSynchronizer::FetchRendererHistogramsAsynchronously( |
| 969 MessageLoop::current(), callback_task, | 918 MessageLoop::current(), callback_task, |
| 970 kMaxHistogramGatheringWaitDuration); | 919 kMaxHistogramGatheringWaitDuration); |
| 971 | 920 |
| 972 // Collect WebCore cache information to put into a histogram. | 921 // Collect WebCore cache information to put into a histogram. |
| 973 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); | 922 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); |
| 974 !i.IsAtEnd(); i.Advance()) | 923 !i.IsAtEnd(); i.Advance()) |
| 975 i.GetCurrentValue()->Send(new ViewMsg_GetCacheResourceStats()); | 924 i.GetCurrentValue()->Send(new ViewMsg_GetCacheResourceStats()); |
| 976 } | 925 } |
| 977 | 926 |
| 978 void MetricsService::OnHistogramSynchronizationDone() { | 927 void MetricsService::OnHistogramSynchronizationDone() { |
| 979 DCHECK(IsSingleThreaded()); | 928 DCHECK(IsSingleThreaded()); |
| 980 | 929 |
| 981 // This function should only be called via timer, so timer_pending_ | 930 // This function should only be called as the callback from an ansynchronous |
| 982 // should be true. | 931 // step. |
| 983 DCHECK(timer_pending_); | 932 DCHECK(waiting_for_asynchronus_reporting_step_); |
| 984 timer_pending_ = false; | 933 waiting_for_asynchronus_reporting_step_ = false; |
|
jar (doing other things)
2011/04/16 02:03:13
If you move this line down to line 944, then you w
stuartmorgan
2011/04/18 17:03:00
Done.
| |
| 985 | 934 |
| 935 // If somehow there is a fetch in progress, we return setting | |
| 936 // waiting_for_asynchronus_reporting_step_ back to true and hope things work | |
| 937 // out. The scheduler isn't informed since if this happens, the scheduler | |
| 938 // will get a response from the upload. | |
| 986 DCHECK(!current_fetch_.get()); | 939 DCHECK(!current_fetch_.get()); |
| 940 if (current_fetch_.get()) { | |
| 941 waiting_for_asynchronus_reporting_step_ = true; | |
| 942 return; | |
| 943 } | |
| 987 | 944 |
| 988 // If we're getting no notifications, then the log won't have much in it, and | 945 // If we're getting no notifications, then the log won't have much in it, and |
| 989 // it's possible the computer is about to go to sleep, so don't upload and | 946 // it's possible the computer is about to go to sleep, so don't upload and |
| 990 // don't restart the transmission timer. | 947 // stop the scheduler. |
| 991 if (idle_since_last_transmission_) | 948 // Similarly, if logs should no longer be uploaded, stop here. |
| 992 return; | 949 if (idle_since_last_transmission_ || |
| 993 | 950 !recording_active() || !reporting_active()) { |
| 994 // If somehow there is a fetch in progress, we return setting timer_pending_ | 951 scheduler_->Stop(); |
|
jar (doing other things)
2011/04/16 02:03:13
Stop() appears to be very permanent. This seems l
stuartmorgan
2011/04/18 17:03:00
The observer calls Start() (just as it used to cal
| |
| 995 // to true and hope things work out. | 952 scheduler_->UploadCancelled(); |
| 996 if (current_fetch_.get()) { | |
| 997 timer_pending_ = true; | |
| 998 return; | 953 return; |
| 999 } | 954 } |
| 1000 | 955 |
| 1001 // If uploads are forbidden by UMA response, there's no point in keeping | |
| 1002 // the current_log_, and the more often we delete it, the less likely it is | |
| 1003 // to expand forever. | |
| 1004 if (!server_permits_upload_ && current_log_) { | |
| 1005 StopRecording(NULL); | |
| 1006 StartRecording(); | |
| 1007 } | |
| 1008 | |
| 1009 if (!current_log_) | |
| 1010 return; // Logging was disabled. | |
| 1011 if (!reporting_active()) | |
| 1012 return; // Don't do work if we're not going to send anything now. | |
| 1013 | |
| 1014 MakePendingLog(); | 956 MakePendingLog(); |
| 1015 | 957 |
| 1016 // MakePendingLog should have put something in the pending log, if it didn't, | 958 // MakePendingLog should have put something in the pending log, if it didn't, |
| 1017 // we start the timer again, return and hope things work out. | 959 // we skip this upload and hope things work out next time. |
| 1018 if (!pending_log()) { | 960 if (!pending_log()) { |
| 1019 StartLogTransmissionTimer(); | 961 scheduler_->UploadCancelled(); |
| 1020 return; | 962 return; |
| 1021 } | 963 } |
| 1022 | 964 |
| 1023 // If we're not supposed to upload any UMA data because the response said so, | |
| 1024 // cancel the upload at this point, but start the timer. | |
| 1025 if (!ServerPermitsTransmission()) { | |
| 1026 DiscardPendingLog(); | |
| 1027 StartLogTransmissionTimer(); | |
| 1028 return; | |
| 1029 } | |
| 1030 | |
| 1031 PrepareFetchWithPendingLog(); | 965 PrepareFetchWithPendingLog(); |
| 1032 | 966 |
| 1033 if (!current_fetch_.get()) { | 967 if (!current_fetch_.get()) { |
| 1034 // Compression failed, and log discarded :-/. | 968 // Compression failed, and log discarded :-/. |
| 1035 DiscardPendingLog(); | 969 DiscardPendingLog(); |
| 1036 StartLogTransmissionTimer(); // Maybe we'll do better next time | 970 scheduler_->UploadCancelled(); |
| 1037 // TODO(jar): If compression failed, we should have created a tiny log and | 971 // TODO(jar): If compression failed, we should have created a tiny log and |
| 1038 // compressed that, so that we can signal that we're losing logs. | 972 // compressed that, so that we can signal that we're losing logs. |
| 1039 return; | 973 return; |
| 1040 } | 974 } |
| 1041 | 975 |
| 1042 DCHECK(!timer_pending_); | 976 DCHECK(!waiting_for_asynchronus_reporting_step_); |
| 1043 | 977 |
| 1044 // The URL fetch is a like timer in that after a while we get called back | 978 waiting_for_asynchronus_reporting_step_ = true; |
| 1045 // so we set timer_pending_ true just as we start the url fetch. | |
| 1046 timer_pending_ = true; | |
| 1047 current_fetch_->Start(); | 979 current_fetch_->Start(); |
| 1048 | 980 |
| 1049 HandleIdleSinceLastTransmission(true); | 981 HandleIdleSinceLastTransmission(true); |
| 1050 } | 982 } |
| 1051 | 983 |
| 1052 | 984 |
| 1053 void MetricsService::MakePendingLog() { | 985 void MetricsService::MakePendingLog() { |
| 1054 if (pending_log()) | 986 if (pending_log()) |
| 1055 return; | 987 return; |
| 1056 | 988 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1092 break; | 1024 break; |
| 1093 | 1025 |
| 1094 default: | 1026 default: |
| 1095 NOTREACHED(); | 1027 NOTREACHED(); |
| 1096 return; | 1028 return; |
| 1097 } | 1029 } |
| 1098 | 1030 |
| 1099 DCHECK(pending_log()); | 1031 DCHECK(pending_log()); |
| 1100 } | 1032 } |
| 1101 | 1033 |
| 1102 bool MetricsService::ServerPermitsTransmission() const { | |
| 1103 // If the server forbids uploading, we take that to mean it forbids current | |
| 1104 // logs, but we still send up the inital logs and any old logs. | |
| 1105 if (server_permits_upload_) | |
| 1106 return true; | |
| 1107 | |
| 1108 switch (state_) { | |
| 1109 case INITIAL_LOG_READY: | |
| 1110 case SEND_OLD_INITIAL_LOGS: | |
| 1111 case SENDING_OLD_LOGS: | |
| 1112 return true; | |
| 1113 | |
| 1114 case SENDING_CURRENT_LOGS: | |
| 1115 default: | |
| 1116 return false; | |
| 1117 } | |
| 1118 } | |
| 1119 | |
| 1120 void MetricsService::PrepareInitialLog() { | 1034 void MetricsService::PrepareInitialLog() { |
| 1121 DCHECK(state_ == INIT_TASK_DONE); | 1035 DCHECK(state_ == INIT_TASK_DONE); |
| 1122 | 1036 |
| 1123 MetricsLog* log = new MetricsLog(client_id_, session_id_); | 1037 MetricsLog* log = new MetricsLog(client_id_, session_id_); |
| 1124 log->set_hardware_class(hardware_class_); // Adds to initial log. | 1038 log->set_hardware_class(hardware_class_); // Adds to initial log. |
| 1125 log->RecordEnvironment(plugins_, profile_dictionary_.get()); | 1039 log->RecordEnvironment(plugins_, profile_dictionary_.get()); |
| 1126 | 1040 |
| 1127 // Histograms only get written to current_log_, so setup for the write. | 1041 // Histograms only get written to current_log_, so setup for the write. |
| 1128 MetricsLogBase* save_log = current_log_; | 1042 MetricsLogBase* save_log = current_log_; |
| 1129 current_log_ = log; | 1043 current_log_ = log; |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1328 return "Unknown"; | 1242 return "Unknown"; |
| 1329 } | 1243 } |
| 1330 } | 1244 } |
| 1331 | 1245 |
| 1332 void MetricsService::OnURLFetchComplete(const URLFetcher* source, | 1246 void MetricsService::OnURLFetchComplete(const URLFetcher* source, |
| 1333 const GURL& url, | 1247 const GURL& url, |
| 1334 const net::URLRequestStatus& status, | 1248 const net::URLRequestStatus& status, |
| 1335 int response_code, | 1249 int response_code, |
| 1336 const ResponseCookies& cookies, | 1250 const ResponseCookies& cookies, |
| 1337 const std::string& data) { | 1251 const std::string& data) { |
| 1338 DCHECK(timer_pending_); | 1252 DCHECK(waiting_for_asynchronus_reporting_step_); |
| 1339 timer_pending_ = false; | 1253 waiting_for_asynchronus_reporting_step_ = false; |
| 1340 DCHECK(current_fetch_.get()); | 1254 DCHECK(current_fetch_.get()); |
| 1341 current_fetch_.reset(NULL); // We're not allowed to re-use it. | 1255 current_fetch_.reset(NULL); // We're not allowed to re-use it. |
| 1342 | 1256 |
| 1343 // Confirm send so that we can move on. | 1257 // Confirm send so that we can move on. |
| 1344 VLOG(1) << "METRICS RESPONSE CODE: " << response_code | 1258 VLOG(1) << "METRICS RESPONSE CODE: " << response_code |
| 1345 << " status=" << StatusToString(status); | 1259 << " status=" << StatusToString(status); |
| 1346 | 1260 |
| 1261 bool upload_succeeded = response_code == 200; | |
| 1262 | |
| 1347 // Provide boolean for error recovery (allow us to ignore response_code). | 1263 // Provide boolean for error recovery (allow us to ignore response_code). |
| 1348 bool discard_log = false; | 1264 bool discard_log = false; |
| 1349 | 1265 |
| 1350 if (response_code != 200 && | 1266 if (!upload_succeeded && |
| 1351 (compressed_log_.length() > | 1267 (compressed_log_.length() > |
| 1352 static_cast<size_t>(kUploadLogAvoidRetransmitSize))) { | 1268 static_cast<size_t>(kUploadLogAvoidRetransmitSize))) { |
| 1353 UMA_HISTOGRAM_COUNTS("UMA.Large Rejected Log was Discarded", | 1269 UMA_HISTOGRAM_COUNTS("UMA.Large Rejected Log was Discarded", |
| 1354 static_cast<int>(compressed_log_.length())); | 1270 static_cast<int>(compressed_log_.length())); |
| 1355 discard_log = true; | 1271 discard_log = true; |
| 1356 } else if (response_code == 400) { | 1272 } else if (response_code == 400) { |
| 1357 // Bad syntax. Retransmission won't work. | 1273 // Bad syntax. Retransmission won't work. |
| 1358 UMA_HISTOGRAM_COUNTS("UMA.Unacceptable_Log_Discarded", state_); | 1274 UMA_HISTOGRAM_COUNTS("UMA.Unacceptable_Log_Discarded", state_); |
| 1359 discard_log = true; | 1275 discard_log = true; |
| 1360 } | 1276 } |
| 1361 | 1277 |
| 1362 if (response_code != 200 && !discard_log) { | 1278 if (!upload_succeeded && !discard_log) { |
| 1363 VLOG(1) << "METRICS: transmission attempt returned a failure code: " | 1279 VLOG(1) << "METRICS: transmission attempt returned a failure code: " |
| 1364 << response_code << ". Verify network connectivity"; | 1280 << response_code << ". Verify network connectivity"; |
| 1365 HandleBadResponseCode(); | 1281 LogBadResponseCode(); |
| 1366 } else { // Successful receipt (or we are discarding log). | 1282 } else { // Successful receipt (or we are discarding log). |
| 1367 VLOG(1) << "METRICS RESPONSE DATA: " << data; | 1283 VLOG(1) << "METRICS RESPONSE DATA: " << data; |
| 1368 switch (state_) { | 1284 switch (state_) { |
| 1369 case INITIAL_LOG_READY: | 1285 case INITIAL_LOG_READY: |
| 1370 state_ = SEND_OLD_INITIAL_LOGS; | 1286 state_ = SEND_OLD_INITIAL_LOGS; |
| 1371 break; | 1287 break; |
| 1372 | 1288 |
| 1373 case SEND_OLD_INITIAL_LOGS: | 1289 case SEND_OLD_INITIAL_LOGS: |
| 1374 DCHECK(!unsent_initial_logs_.empty()); | 1290 DCHECK(!unsent_initial_logs_.empty()); |
| 1375 unsent_initial_logs_.pop_back(); | 1291 unsent_initial_logs_.pop_back(); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 1390 break; | 1306 break; |
| 1391 } | 1307 } |
| 1392 | 1308 |
| 1393 DiscardPendingLog(); | 1309 DiscardPendingLog(); |
| 1394 // Since we sent a log, make sure our in-memory state is recorded to disk. | 1310 // Since we sent a log, make sure our in-memory state is recorded to disk. |
| 1395 PrefService* local_state = g_browser_process->local_state(); | 1311 PrefService* local_state = g_browser_process->local_state(); |
| 1396 DCHECK(local_state); | 1312 DCHECK(local_state); |
| 1397 if (local_state) | 1313 if (local_state) |
| 1398 local_state->ScheduleSavePersistentPrefs(); | 1314 local_state->ScheduleSavePersistentPrefs(); |
| 1399 | 1315 |
| 1400 // Override usual interlog delay if there are unsent logs to transmit, | 1316 if (unsent_logs()) |
| 1401 // otherwise reset back to default. | |
| 1402 if (unsent_logs()) { | |
| 1403 DCHECK(state_ < SENDING_CURRENT_LOGS); | 1317 DCHECK(state_ < SENDING_CURRENT_LOGS); |
| 1404 interlog_duration_ = TimeDelta::FromSeconds(kUnsentLogDelay); | |
| 1405 } else { | |
| 1406 interlog_duration_ = TimeDelta::FromSeconds(kMinSecondsPerLog); | |
| 1407 } | |
| 1408 } | 1318 } |
| 1409 | 1319 |
| 1410 StartLogTransmissionTimer(); | 1320 // Error 400 indicates a problem with the log, not with the server, so |
| 1321 // don't consider that a sign that the server is in trouble. | |
| 1322 bool server_is_healthy = upload_succeeded || response_code == 400; | |
| 1323 | |
| 1324 scheduler_->UploadFinished(server_is_healthy, unsent_logs()); | |
| 1411 } | 1325 } |
| 1412 | 1326 |
| 1413 void MetricsService::HandleBadResponseCode() { | 1327 void MetricsService::LogBadResponseCode() { |
| 1414 VLOG(1) << "Verify your metrics logs are formatted correctly. Verify server " | 1328 VLOG(1) << "Verify your metrics logs are formatted correctly. Verify server " |
| 1415 "is active at " << server_url_; | 1329 "is active at " << server_url_; |
| 1416 if (!pending_log()) { | 1330 if (!pending_log()) { |
| 1417 VLOG(1) << "METRICS: Recorder shutdown during log transmission."; | 1331 VLOG(1) << "METRICS: Recorder shutdown during log transmission."; |
| 1418 } else { | 1332 } else { |
| 1419 // Send progressively less frequently. | 1333 VLOG(1) << "METRICS: transmission retry being scheduled for " |
| 1420 DCHECK(kBackoff > 1.0); | |
| 1421 interlog_duration_ = TimeDelta::FromMicroseconds( | |
| 1422 static_cast<int64>(kBackoff * interlog_duration_.InMicroseconds())); | |
| 1423 | |
| 1424 if (kMaxBackoff * TimeDelta::FromSeconds(kMinSecondsPerLog) < | |
| 1425 interlog_duration_) { | |
| 1426 interlog_duration_ = kMaxBackoff * | |
| 1427 TimeDelta::FromSeconds(kMinSecondsPerLog); | |
| 1428 } | |
| 1429 | |
| 1430 VLOG(1) << "METRICS: transmission retry being scheduled in " | |
| 1431 << interlog_duration_.InSeconds() << " seconds for " | |
| 1432 << compressed_log_; | 1334 << compressed_log_; |
| 1433 } | 1335 } |
| 1434 } | 1336 } |
| 1435 | 1337 |
| 1436 void MetricsService::LogWindowChange(NotificationType type, | 1338 void MetricsService::LogWindowChange(NotificationType type, |
| 1437 const NotificationSource& source, | 1339 const NotificationSource& source, |
| 1438 const NotificationDetails& details) { | 1340 const NotificationDetails& details) { |
| 1439 int controller_id = -1; | 1341 int controller_id = -1; |
| 1440 uintptr_t window_or_tab = source.map_key(); | 1342 uintptr_t window_or_tab = source.map_key(); |
| 1441 MetricsLog::WindowEventType window_type; | 1343 MetricsLog::WindowEventType window_type; |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1739 thread_id = base::PlatformThread::CurrentId(); | 1641 thread_id = base::PlatformThread::CurrentId(); |
| 1740 return base::PlatformThread::CurrentId() == thread_id; | 1642 return base::PlatformThread::CurrentId() == thread_id; |
| 1741 } | 1643 } |
| 1742 | 1644 |
| 1743 #if defined(OS_CHROMEOS) | 1645 #if defined(OS_CHROMEOS) |
| 1744 void MetricsService::StartExternalMetrics() { | 1646 void MetricsService::StartExternalMetrics() { |
| 1745 external_metrics_ = new chromeos::ExternalMetrics; | 1647 external_metrics_ = new chromeos::ExternalMetrics; |
| 1746 external_metrics_->Start(); | 1648 external_metrics_->Start(); |
| 1747 } | 1649 } |
| 1748 #endif | 1650 #endif |
| OLD | NEW |