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

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

Issue 10078017: Added asynchronous notification of readiness to the StatisticsProvider, and (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Timeout while waiting for the hardware_class; sample UMA stats Created 8 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 //------------------------------------------------------------------------------ 5 //------------------------------------------------------------------------------
6 // Description of the life cycle of a instance of MetricsService. 6 // Description of the life cycle of a instance of MetricsService.
7 // 7 //
8 // OVERVIEW 8 // OVERVIEW
9 // 9 //
10 // A MetricsService instance is typically created at application startup. It 10 // A MetricsService instance is typically created at application startup. It
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 // SENDING_OLD_LOGS, // Sending unsent logs from previous session. 82 // SENDING_OLD_LOGS, // Sending unsent logs from previous session.
83 // SENDING_CURRENT_LOGS, // Sending standard current logs as they accrue. 83 // SENDING_CURRENT_LOGS, // Sending standard current logs as they accrue.
84 // 84 //
85 // In more detail, we have: 85 // In more detail, we have:
86 // 86 //
87 // INITIALIZED, // Constructor was called. 87 // INITIALIZED, // Constructor was called.
88 // The MS has been constructed, but has taken no actions to compose the 88 // The MS has been constructed, but has taken no actions to compose the
89 // initial log. 89 // initial log.
90 // 90 //
91 // INIT_TASK_SCHEDULED, // Waiting for deferred init tasks to complete. 91 // INIT_TASK_SCHEDULED, // Waiting for deferred init tasks to complete.
92 // Typically about 30 seconds after startup, a task is sent to a second thread 92 // Typically about 30 seconds after startup, a task is posted to perform
93 // (the file thread) to perform deferred (lower priority and slower) 93 // deferred (lower priority and slower) initialization steps such as getting the
94 // initialization steps such as getting the list of plugins. That task will 94 // list of plugins. That task will (when complete) make an async callback (via
95 // (when complete) make an async callback (via a Task) to indicate the 95 // a Task) to indicate the completion.
96 // completion.
97 // 96 //
98 // INIT_TASK_DONE, // Waiting for timer to send initial log. 97 // INIT_TASK_DONE, // Waiting for timer to send initial log.
99 // The callback has arrived, and it is now possible for an initial log to be 98 // The callback has arrived, and it is now possible for an initial log to be
100 // created. This callback typically arrives back less than one second after 99 // created. This callback typically arrives back less than one second after
101 // the deferred init task is dispatched. 100 // the deferred init task is dispatched.
102 // 101 //
103 // INITIAL_LOG_READY, // Initial log generated, and waiting for reply. 102 // INITIAL_LOG_READY, // Initial log generated, and waiting for reply.
104 // This state is entered only after an initial log has been composed, and 103 // This state is entered only after an initial log has been composed, and
105 // prepared for transmission. It is also the case that any previously unsent 104 // prepared for transmission. It is also the case that any previously unsent
106 // logs have been loaded into instance variables for possible transmission. 105 // logs have been loaded into instance variables for possible transmission.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 145
147 #include "base/bind.h" 146 #include "base/bind.h"
148 #include "base/callback.h" 147 #include "base/callback.h"
149 #include "base/command_line.h" 148 #include "base/command_line.h"
150 #include "base/md5.h" 149 #include "base/md5.h"
151 #include "base/metrics/histogram.h" 150 #include "base/metrics/histogram.h"
152 #include "base/string_number_conversions.h" 151 #include "base/string_number_conversions.h"
153 #include "base/threading/platform_thread.h" 152 #include "base/threading/platform_thread.h"
154 #include "base/threading/thread.h" 153 #include "base/threading/thread.h"
155 #include "base/threading/thread_restrictions.h" 154 #include "base/threading/thread_restrictions.h"
155 #include "base/time.h"
156 #include "base/tracked_objects.h" 156 #include "base/tracked_objects.h"
157 #include "base/utf_string_conversions.h" 157 #include "base/utf_string_conversions.h"
158 #include "base/values.h" 158 #include "base/values.h"
159 #include "chrome/browser/bookmarks/bookmark_model.h" 159 #include "chrome/browser/bookmarks/bookmark_model.h"
160 #include "chrome/browser/browser_process.h" 160 #include "chrome/browser/browser_process.h"
161 #include "chrome/browser/extensions/extension_service.h" 161 #include "chrome/browser/extensions/extension_service.h"
162 #include "chrome/browser/extensions/process_map.h" 162 #include "chrome/browser/extensions/process_map.h"
163 #include "chrome/browser/io_thread.h" 163 #include "chrome/browser/io_thread.h"
164 #include "chrome/browser/memory_details.h" 164 #include "chrome/browser/memory_details.h"
165 #include "chrome/browser/metrics/histogram_synchronizer.h" 165 #include "chrome/browser/metrics/histogram_synchronizer.h"
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 const char kMetricsTypeProto[] = "application/vnd.chrome.uma"; 222 const char kMetricsTypeProto[] = "application/vnd.chrome.uma";
223 223
224 const char kServerUrlXml[] = 224 const char kServerUrlXml[] =
225 "https://clients4.google.com/firefox/metrics/collect"; 225 "https://clients4.google.com/firefox/metrics/collect";
226 const char kServerUrlProto[] = "https://clients4.google.com/uma/v2"; 226 const char kServerUrlProto[] = "https://clients4.google.com/uma/v2";
227 227
228 // The delay, in seconds, after starting recording before doing expensive 228 // The delay, in seconds, after starting recording before doing expensive
229 // initialization work. 229 // initialization work.
230 const int kInitializationDelaySeconds = 30; 230 const int kInitializationDelaySeconds = 30;
231 231
232 // The timeout, in seconds, to resume initialization of the MetricsService if
233 // the initialization of the StatisticsProvider hasn't completed yet.
234 const int kStatisticsProviderTimeoutSeconds = 300;
235
232 // This specifies the amount of time to wait for all renderers to send their 236 // This specifies the amount of time to wait for all renderers to send their
233 // data. 237 // data.
234 const int kMaxHistogramGatheringWaitDuration = 60000; // 60 seconds. 238 const int kMaxHistogramGatheringWaitDuration = 60000; // 60 seconds.
235 239
236 // The maximum number of events in a log uploaded to the UMA server. 240 // The maximum number of events in a log uploaded to the UMA server.
237 const int kEventLimit = 2400; 241 const int kEventLimit = 2400;
238 242
239 // If an upload fails, and the transmission was over this byte count, then we 243 // If an upload fails, and the transmission was over this byte count, then we
240 // will discard the log, and not try to retransmit it. We also don't persist 244 // will discard the log, and not try to retransmit it. We also don't persist
241 // the log to the prefs for transmission during the next chrome session if this 245 // the log to the prefs for transmission during the next chrome session if this
242 // limit is exceeded. 246 // limit is exceeded.
243 const size_t kUploadLogAvoidRetransmitSize = 50000; 247 const size_t kUploadLogAvoidRetransmitSize = 50000;
244 248
245 // Interval, in minutes, between state saves. 249 // Interval, in minutes, between state saves.
246 const int kSaveStateIntervalMinutes = 5; 250 const int kSaveStateIntervalMinutes = 5;
247 251
248 // Used to indicate that the response code is currently not set at all -- 252 // Used to indicate that the response code is currently not set at all --
249 // RESPONSE_CODE_INVALID can sometimes be returned in response to a request if, 253 // RESPONSE_CODE_INVALID can sometimes be returned in response to a request if,
250 // e.g., the server is down. 254 // e.g., the server is down.
251 const int kNoResponseCode = content::URLFetcher::RESPONSE_CODE_INVALID - 1; 255 const int kNoResponseCode = content::URLFetcher::RESPONSE_CODE_INVALID - 1;
252 256
257 // Used to indicate that a report was generated before the hardware_class
258 // property was available from the StatisticsProvider. This is used to identify
259 // faulty reports from Chrome OS clients.
260 const char kHardwareClassNotReady[] = "(not ready)";
261
253 } 262 }
254 263
255 // static 264 // static
256 MetricsService::ShutdownCleanliness MetricsService::clean_shutdown_status_ = 265 MetricsService::ShutdownCleanliness MetricsService::clean_shutdown_status_ =
257 MetricsService::CLEANLY_SHUTDOWN; 266 MetricsService::CLEANLY_SHUTDOWN;
258 267
259 // This is used to quickly log stats from child process related notifications in 268 // This is used to quickly log stats from child process related notifications in
260 // MetricsService::child_stats_buffer_. The buffer's contents are transferred 269 // MetricsService::child_stats_buffer_. The buffer's contents are transferred
261 // out when Local State is periodically saved. The information is then 270 // out when Local State is periodically saved. The information is then
262 // reported to the UMA server on next launch. 271 // reported to the UMA server on next launch.
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 } 402 }
394 403
395 MetricsService::MetricsService() 404 MetricsService::MetricsService()
396 : recording_active_(false), 405 : recording_active_(false),
397 reporting_active_(false), 406 reporting_active_(false),
398 state_(INITIALIZED), 407 state_(INITIALIZED),
399 idle_since_last_transmission_(false), 408 idle_since_last_transmission_(false),
400 next_window_id_(0), 409 next_window_id_(0),
401 ALLOW_THIS_IN_INITIALIZER_LIST(self_ptr_factory_(this)), 410 ALLOW_THIS_IN_INITIALIZER_LIST(self_ptr_factory_(this)),
402 ALLOW_THIS_IN_INITIALIZER_LIST(state_saver_factory_(this)), 411 ALLOW_THIS_IN_INITIALIZER_LIST(state_saver_factory_(this)),
412 ALLOW_THIS_IN_INITIALIZER_LIST(timeout_task_factory_(this)),
403 waiting_for_asynchronus_reporting_step_(false) { 413 waiting_for_asynchronus_reporting_step_(false) {
404 DCHECK(IsSingleThreaded()); 414 DCHECK(IsSingleThreaded());
405 InitializeMetricsState(); 415 InitializeMetricsState();
406 416
407 base::Closure callback = base::Bind(&MetricsService::StartScheduledUpload, 417 base::Closure callback = base::Bind(&MetricsService::StartScheduledUpload,
408 self_ptr_factory_.GetWeakPtr()); 418 self_ptr_factory_.GetWeakPtr());
409 scheduler_.reset(new MetricsReportingScheduler(callback)); 419 scheduler_.reset(new MetricsReportingScheduler(callback));
410 log_manager_.set_log_serializer(new MetricsLogSerializer()); 420 log_manager_.set_log_serializer(new MetricsLogSerializer());
411 log_manager_.set_max_ongoing_log_store_size(kUploadLogAvoidRetransmitSize); 421 log_manager_.set_max_ongoing_log_store_size(kUploadLogAvoidRetransmitSize);
412 } 422 }
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 size_t switch_count = command_line->GetSwitches().size(); 760 size_t switch_count = command_line->GetSwitches().size();
751 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineFlagCount", switch_count); 761 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineFlagCount", switch_count);
752 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineUncommonFlagCount", 762 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineUncommonFlagCount",
753 switch_count - common_commands); 763 switch_count - common_commands);
754 764
755 // Kick off the process of saving the state (so the uptime numbers keep 765 // Kick off the process of saving the state (so the uptime numbers keep
756 // getting updated) every n minutes. 766 // getting updated) every n minutes.
757 ScheduleNextStateSave(); 767 ScheduleNextStateSave();
758 } 768 }
759 769
760 // static 770 void MetricsService::InitTaskGetHardwareClass() {
761 void MetricsService::InitTaskGetHardwareClass( 771 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
762 base::WeakPtr<MetricsService> self, 772 DCHECK_EQ(INIT_TASK_SCHEDULED, state_);
763 base::MessageLoopProxy* target_loop) {
764 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
765 773
766 std::string hardware_class;
767 #if defined(OS_CHROMEOS) 774 #if defined(OS_CHROMEOS)
768 chromeos::system::StatisticsProvider::GetInstance()->GetMachineStatistic( 775 // The hardware class can only be retrieved once the StatisticsProvider is
769 "hardware_class", &hardware_class); 776 // ready. This usually happens early enough, but can take longer on some
770 #endif // OS_CHROMEOS 777 // faulty hardware.
778 chromeos::system::StatisticsProvider::GetInstance()->WhenReady(
779 base::Bind(&MetricsService::OnStatisticsProviderReady,
780 self_ptr_factory_.GetWeakPtr(),
781 base::Time::Now()));
771 782
772 target_loop->PostTask(FROM_HERE, 783 // Set up a timeout task in case the StatisticsProvider takes too long to
773 base::Bind(&MetricsService::OnInitTaskGotHardwareClass, 784 // initialize. Only one of these tasks will execute; invoking either
774 self, hardware_class)); 785 // invalidates the WeakPtr of the other. In both cases, hardware_class_ is
786 // updated once OnStatisticsProviderReady is invoked.
787
788 // Invoke the next init task if the StatisticsProvider becomes ready.
789 // This will be invoked immediately after OnStatisticsProviderReady.
790 chromeos::system::StatisticsProvider::GetInstance()->WhenReady(
791 base::Bind(&MetricsService::InitTaskGetPluginInfo,
792 timeout_task_factory_.GetWeakPtr()));
793
794 // Invoke OnStatisticsProviderTimeout if it times out instead.
795 MessageLoop::current()->PostDelayedTask(
796 FROM_HERE,
797 base::Bind(&MetricsService::OnStatisticsProviderTimeout,
798 timeout_task_factory_.GetWeakPtr()),
799 base::TimeDelta::FromSeconds(kStatisticsProviderTimeoutSeconds));
800 #else
801 InitTaskGetPluginInfo();
802 #endif
775 } 803 }
776 804
777 void MetricsService::OnInitTaskGotHardwareClass( 805 void MetricsService::OnStatisticsProviderReady(const base::Time& start_time) {
778 const std::string& hardware_class) { 806 #if defined(OS_CHROMEOS)
807 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
808 base::TimeDelta elapsed = base::Time::Now() - start_time;
809 UMA_HISTOGRAM_LONG_TIMES("UMA.StatisticsProviderReadyDelay", elapsed);
810 chromeos::system::StatisticsProvider::GetInstance()->GetMachineStatistic(
811 "hardware_class", &hardware_class_);
812 #endif
813 }
814
815 void MetricsService::OnStatisticsProviderTimeout() {
Ilya Sherman 2012/04/30 07:36:41 nit: Perhaps log a histogram/event for the timeout
Joao da Silva 2012/05/15 13:52:47 Good idea. I've moved these histograms to the Stat
816 #if defined(OS_CHROMEOS)
817 // Use an invalid hardware_class temporarily until the StatisticsProvider is
818 // ready.
Ilya Sherman 2012/04/30 07:36:41 It looks like, with this setup, we'll never record
Joao da Silva 2012/05/15 13:52:47 The WhenReady() callback is still pending in this
819 hardware_class_ = kHardwareClassNotReady;
820 InitTaskGetPluginInfo();
821 #endif
822 }
823
824 void MetricsService::InitTaskGetPluginInfo() {
825 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
779 DCHECK_EQ(INIT_TASK_SCHEDULED, state_); 826 DCHECK_EQ(INIT_TASK_SCHEDULED, state_);
780 hardware_class_ = hardware_class; 827
828 // Invalidate tasks related to waiting for the StatisticsProvider to
829 // initialize, if any are still scheduled.
830 timeout_task_factory_.InvalidateWeakPtrs();
781 831
782 // Start the next part of the init task: loading plugin information. 832 // Start the next part of the init task: loading plugin information.
783 PluginService::GetInstance()->GetPlugins( 833 PluginService::GetInstance()->GetPlugins(
784 base::Bind(&MetricsService::OnInitTaskGotPluginInfo, 834 base::Bind(&MetricsService::OnInitTaskGotPluginInfo,
785 self_ptr_factory_.GetWeakPtr())); 835 self_ptr_factory_.GetWeakPtr()));
786 } 836 }
787 837
788 void MetricsService::OnInitTaskGotPluginInfo( 838 void MetricsService::OnInitTaskGotPluginInfo(
789 const std::vector<webkit::WebPluginInfo>& plugins) { 839 const std::vector<webkit::WebPluginInfo>& plugins) {
790 DCHECK_EQ(INIT_TASK_SCHEDULED, state_); 840 DCHECK_EQ(INIT_TASK_SCHEDULED, state_);
791 plugins_ = plugins; 841 plugins_ = plugins;
792 842
793 // Start the next part of the init task: fetching performance data. This will 843 // Start the next part of the init task: fetching performance data. This will
794 // call into |FinishedReceivingProfilerData()| when the task completes. 844 // call into |FinishedReceivingProfilerData()| when the task completes.
795 chrome_browser_metrics::TrackingSynchronizer::FetchProfilerDataAsynchronously( 845 chrome_browser_metrics::TrackingSynchronizer::FetchProfilerDataAsynchronously(
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
850 void MetricsService::StartRecording() { 900 void MetricsService::StartRecording() {
851 if (log_manager_.current_log()) 901 if (log_manager_.current_log())
852 return; 902 return;
853 903
854 log_manager_.BeginLoggingWithLog(new MetricsLog(client_id_, session_id_), 904 log_manager_.BeginLoggingWithLog(new MetricsLog(client_id_, session_id_),
855 MetricsLogManager::ONGOING_LOG); 905 MetricsLogManager::ONGOING_LOG);
856 if (state_ == INITIALIZED) { 906 if (state_ == INITIALIZED) {
857 // We only need to schedule that run once. 907 // We only need to schedule that run once.
858 state_ = INIT_TASK_SCHEDULED; 908 state_ = INIT_TASK_SCHEDULED;
859 909
860 // Schedules a task on the file thread for execution of slower 910 // Schedules a delayed task for execution of slower initialization steps
861 // initialization steps (such as plugin list generation) necessary 911 // (such as plugin list generation) necessary for sending the initial log.
862 // for sending the initial log. This avoids blocking the main UI 912 MessageLoop::current()->PostDelayedTask(
863 // thread.
864 BrowserThread::PostDelayedTask(
865 BrowserThread::FILE,
866 FROM_HERE, 913 FROM_HERE,
867 base::Bind(&MetricsService::InitTaskGetHardwareClass, 914 base::Bind(&MetricsService::InitTaskGetHardwareClass,
868 self_ptr_factory_.GetWeakPtr(), 915 self_ptr_factory_.GetWeakPtr()),
869 MessageLoop::current()->message_loop_proxy()),
870 base::TimeDelta::FromSeconds(kInitializationDelaySeconds)); 916 base::TimeDelta::FromSeconds(kInitializationDelaySeconds));
871 } 917 }
872 } 918 }
873 919
874 void MetricsService::StopRecording() { 920 void MetricsService::StopRecording() {
875 if (!log_manager_.current_log()) 921 if (!log_manager_.current_log())
876 return; 922 return;
877 923
878 // TODO(jar): Integrate bounds on log recording more consistently, so that we 924 // TODO(jar): Integrate bounds on log recording more consistently, so that we
879 // can stop recording logs that are too big much sooner. 925 // can stop recording logs that are too big much sooner.
(...skipping 816 matching lines...) Expand 10 before | Expand all | Expand 10 after
1696 if (local_state) { 1742 if (local_state) {
1697 const PrefService::Preference* uma_pref = 1743 const PrefService::Preference* uma_pref =
1698 local_state->FindPreference(prefs::kMetricsReportingEnabled); 1744 local_state->FindPreference(prefs::kMetricsReportingEnabled);
1699 if (uma_pref) { 1745 if (uma_pref) {
1700 bool success = uma_pref->GetValue()->GetAsBoolean(&result); 1746 bool success = uma_pref->GetValue()->GetAsBoolean(&result);
1701 DCHECK(success); 1747 DCHECK(success);
1702 } 1748 }
1703 } 1749 }
1704 return result; 1750 return result;
1705 } 1751 }
OLDNEW
« chrome/browser/metrics/metrics_service.h ('K') | « chrome/browser/metrics/metrics_service.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698