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

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: Rebased to trunk 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
« no previous file with comments | « chrome/browser/metrics/metrics_service.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « chrome/browser/metrics/metrics_service.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698