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

Side by Side Diff: chrome/browser/metrics/metrics_service.cc

Issue 6869034: Factor a scheduler object out of MetricsService. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Comment fix Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698