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

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: . Created 8 years, 7 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 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 #include "webkit/plugins/webplugininfo.h" 191 #include "webkit/plugins/webplugininfo.h"
193 192
194 // TODO(port): port browser_distribution.h. 193 // TODO(port): port browser_distribution.h.
195 #if !defined(OS_POSIX) 194 #if !defined(OS_POSIX)
196 #include "chrome/installer/util/browser_distribution.h" 195 #include "chrome/installer/util/browser_distribution.h"
197 #endif 196 #endif
198 197
199 #if defined(OS_CHROMEOS) 198 #if defined(OS_CHROMEOS)
200 #include "chrome/browser/chromeos/cros/cros_library.h" 199 #include "chrome/browser/chromeos/cros/cros_library.h"
201 #include "chrome/browser/chromeos/external_metrics.h" 200 #include "chrome/browser/chromeos/external_metrics.h"
202 #include "chrome/browser/chromeos/system/statistics_provider.h"
203 #endif 201 #endif
204 202
205 using base::Time; 203 using base::Time;
206 using content::BrowserThread; 204 using content::BrowserThread;
207 using content::ChildProcessData; 205 using content::ChildProcessData;
208 using content::LoadNotificationDetails; 206 using content::LoadNotificationDetails;
209 using content::PluginService; 207 using content::PluginService;
210 208
211 namespace { 209 namespace {
212 210
213 // Check to see that we're being called on only one thread. 211 // Check to see that we're being called on only one thread.
214 bool IsSingleThreaded() { 212 bool IsSingleThreaded() {
215 static base::PlatformThreadId thread_id = 0; 213 static base::PlatformThreadId thread_id = 0;
216 if (!thread_id) 214 if (!thread_id)
217 thread_id = base::PlatformThread::CurrentId(); 215 thread_id = base::PlatformThread::CurrentId();
218 return base::PlatformThread::CurrentId() == thread_id; 216 return base::PlatformThread::CurrentId() == thread_id;
219 } 217 }
220 218
221 // The delay, in seconds, after starting recording before doing expensive 219 // The delay, in seconds, after starting recording before doing expensive
222 // initialization work. 220 // initialization work.
223 const int kInitializationDelaySeconds = 30; 221 const int kInitializationDelaySeconds = 30;
224 222
223 // The timeout, in seconds, to resume initialization of the MetricsService if
224 // the initialization of the StatisticsProvider hasn't completed yet.
225 const int kStatisticsProviderTimeoutSeconds = 300;
226
225 // 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
226 // data. 228 // data.
227 const int kMaxHistogramGatheringWaitDuration = 60000; // 60 seconds. 229 const int kMaxHistogramGatheringWaitDuration = 60000; // 60 seconds.
228 230
229 // 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.
230 const int kEventLimit = 2400; 232 const int kEventLimit = 2400;
231 233
232 // 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
233 // 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
234 // 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
235 // limit is exceeded. 237 // limit is exceeded.
236 const size_t kUploadLogAvoidRetransmitSize = 50000; 238 const size_t kUploadLogAvoidRetransmitSize = 50000;
237 239
238 // Interval, in minutes, between state saves. 240 // Interval, in minutes, between state saves.
239 const int kSaveStateIntervalMinutes = 5; 241 const int kSaveStateIntervalMinutes = 5;
240 242
241 // Used to indicate that the response code is currently not set at all -- 243 // Used to indicate that the response code is currently not set at all --
242 // RESPONSE_CODE_INVALID can sometimes be returned in response to a request if, 244 // RESPONSE_CODE_INVALID can sometimes be returned in response to a request if,
243 // e.g., the server is down. 245 // e.g., the server is down.
244 const int kNoResponseCode = content::URLFetcher::RESPONSE_CODE_INVALID - 1; 246 const int kNoResponseCode = content::URLFetcher::RESPONSE_CODE_INVALID - 1;
245 247
248 // Used to indicate that a report was generated before the hardware_class
249 // property was available from the StatisticsProvider. This is used to identify
250 // faulty reports from Chrome OS clients.
251 const char kHardwareClassNotReady[] = "(not ready)";
252
246 } 253 }
247 254
248 // static 255 // static
249 MetricsService::ShutdownCleanliness MetricsService::clean_shutdown_status_ = 256 MetricsService::ShutdownCleanliness MetricsService::clean_shutdown_status_ =
250 MetricsService::CLEANLY_SHUTDOWN; 257 MetricsService::CLEANLY_SHUTDOWN;
251 258
252 // This is used to quickly log stats from child process related notifications in 259 // This is used to quickly log stats from child process related notifications in
253 // MetricsService::child_stats_buffer_. The buffer's contents are transferred 260 // MetricsService::child_stats_buffer_. The buffer's contents are transferred
254 // out when Local State is periodically saved. The information is then 261 // out when Local State is periodically saved. The information is then
255 // reported to the UMA server on next launch. 262 // reported to the UMA server on next launch.
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 406
400 base::Closure callback = base::Bind(&MetricsService::StartScheduledUpload, 407 base::Closure callback = base::Bind(&MetricsService::StartScheduledUpload,
401 self_ptr_factory_.GetWeakPtr()); 408 self_ptr_factory_.GetWeakPtr());
402 scheduler_.reset(new MetricsReportingScheduler(callback)); 409 scheduler_.reset(new MetricsReportingScheduler(callback));
403 log_manager_.set_log_serializer(new MetricsLogSerializer()); 410 log_manager_.set_log_serializer(new MetricsLogSerializer());
404 log_manager_.set_max_ongoing_log_store_size(kUploadLogAvoidRetransmitSize); 411 log_manager_.set_max_ongoing_log_store_size(kUploadLogAvoidRetransmitSize);
405 } 412 }
406 413
407 MetricsService::~MetricsService() { 414 MetricsService::~MetricsService() {
408 SetRecording(false); 415 SetRecording(false);
416 #if defined(OS_CHROMEOS)
417 chromeos::system::StatisticsProvider::GetInstance()->RemoveObserver(this);
418 #endif
409 } 419 }
410 420
411 void MetricsService::Start() { 421 void MetricsService::Start() {
412 HandleIdleSinceLastTransmission(false); 422 HandleIdleSinceLastTransmission(false);
413 SetRecording(true); 423 SetRecording(true);
414 SetReporting(true); 424 SetReporting(true);
415 } 425 }
416 426
417 void MetricsService::StartRecordingOnly() { 427 void MetricsService::StartRecordingOnly() {
418 SetRecording(true); 428 SetRecording(true);
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
743 size_t switch_count = command_line->GetSwitches().size(); 753 size_t switch_count = command_line->GetSwitches().size();
744 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineFlagCount", switch_count); 754 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineFlagCount", switch_count);
745 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineUncommonFlagCount", 755 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineUncommonFlagCount",
746 switch_count - common_commands); 756 switch_count - common_commands);
747 757
748 // Kick off the process of saving the state (so the uptime numbers keep 758 // Kick off the process of saving the state (so the uptime numbers keep
749 // getting updated) every n minutes. 759 // getting updated) every n minutes.
750 ScheduleNextStateSave(); 760 ScheduleNextStateSave();
751 } 761 }
752 762
753 // static 763 void MetricsService::InitTaskGetHardwareClass() {
754 void MetricsService::InitTaskGetHardwareClass( 764 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
755 base::WeakPtr<MetricsService> self, 765 DCHECK_EQ(INIT_TASK_SCHEDULED, state_);
756 base::MessageLoopProxy* target_loop) {
757 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
758 766
759 std::string hardware_class;
760 #if defined(OS_CHROMEOS) 767 #if defined(OS_CHROMEOS)
761 chromeos::system::StatisticsProvider::GetInstance()->GetMachineStatistic( 768 // Exactly one of these two callbacks will be invoked. |timeout_callback_|
762 "hardware_class", &hardware_class); 769 // is posted to UI with a certain delay; |on_ready_callback_| is invoked
763 #endif // OS_CHROMEOS 770 // once the StatisticsProvider() becomes ready. Execution of one of these
771 // callbacks cancels the execution of the other.
772 timeout_callback_.Reset(
773 base::Bind(&MetricsService::OnStatisticsProviderTimeout,
774 base::Unretained(this)));
775 on_ready_callback_.Reset(
776 base::Bind(&MetricsService::InitTaskGetPluginInfo,
777 base::Unretained(this)));
764 778
765 target_loop->PostTask(FROM_HERE, 779 BrowserThread::PostDelayedTask(
766 base::Bind(&MetricsService::OnInitTaskGotHardwareClass, 780 BrowserThread::UI, FROM_HERE,
767 self, hardware_class)); 781 timeout_callback_.callback(),
782 base::TimeDelta::FromSeconds(kStatisticsProviderTimeoutSeconds));
783
784 // The hardware class can only be retrieved once the StatisticsProvider is
785 // ready. This usually happens early enough, but can take longer on some
786 // faulty hardware.
787 chromeos::system::StatisticsProvider::GetInstance()->AddObserver(this);
788 #else
789 InitTaskGetPluginInfo();
790 #endif
Ilya Sherman 2012/05/16 01:01:17 nit: Please add " // #if defined(OS_CHROMEOS)"
Joao da Silva 2012/05/16 12:53:34 Done.
768 } 791 }
769 792
770 void MetricsService::OnInitTaskGotHardwareClass( 793 #if defined(OS_CHROMEOS)
771 const std::string& hardware_class) { 794
795 void MetricsService::OnMachineStatisticsReady() {
796 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
797 chromeos::system::StatisticsProvider::GetInstance()->GetMachineStatistic(
798 "hardware_class", &hardware_class_);
799 timeout_callback_.Cancel();
800 if (!on_ready_callback_.IsCancelled())
801 on_ready_callback_.callback().Run();
802 }
803
804 void MetricsService::OnStatisticsProviderTimeout() {
Ilya Sherman 2012/05/16 01:01:17 nit: DCHECK to make sure we're still on the UI thr
Joao da Silva 2012/05/16 12:53:34 Done.
805 // Use an invalid hardware_class temporarily until the StatisticsProvider is
806 // ready.
807 hardware_class_ = kHardwareClassNotReady;
808 on_ready_callback_.Cancel();
809 InitTaskGetPluginInfo();
810 }
811
812 #endif
Ilya Sherman 2012/05/16 01:01:17 nit: Ditto
Joao da Silva 2012/05/16 12:53:34 Done.
813
814 void MetricsService::InitTaskGetPluginInfo() {
815 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
772 DCHECK_EQ(INIT_TASK_SCHEDULED, state_); 816 DCHECK_EQ(INIT_TASK_SCHEDULED, state_);
773 hardware_class_ = hardware_class;
774 817
775 // Start the next part of the init task: loading plugin information. 818 // Start the next part of the init task: loading plugin information.
776 PluginService::GetInstance()->GetPlugins( 819 PluginService::GetInstance()->GetPlugins(
777 base::Bind(&MetricsService::OnInitTaskGotPluginInfo, 820 base::Bind(&MetricsService::OnInitTaskGotPluginInfo,
778 self_ptr_factory_.GetWeakPtr())); 821 self_ptr_factory_.GetWeakPtr()));
779 } 822 }
780 823
781 void MetricsService::OnInitTaskGotPluginInfo( 824 void MetricsService::OnInitTaskGotPluginInfo(
782 const std::vector<webkit::WebPluginInfo>& plugins) { 825 const std::vector<webkit::WebPluginInfo>& plugins) {
783 DCHECK_EQ(INIT_TASK_SCHEDULED, state_); 826 DCHECK_EQ(INIT_TASK_SCHEDULED, state_);
784 plugins_ = plugins; 827 plugins_ = plugins;
785 828
786 // Schedules a task on a blocking pool thread to gather Google Update 829 // Schedules a task on a blocking pool thread to gather Google Update
787 // statistics (requires Registry reads). 830 // statistics (requires Registry reads).
788 BrowserThread::PostBlockingPoolTask( 831 BrowserThread::PostBlockingPoolTask(
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
885 void MetricsService::StartRecording() { 928 void MetricsService::StartRecording() {
886 if (log_manager_.current_log()) 929 if (log_manager_.current_log())
887 return; 930 return;
888 931
889 log_manager_.BeginLoggingWithLog(new MetricsLog(client_id_, session_id_), 932 log_manager_.BeginLoggingWithLog(new MetricsLog(client_id_, session_id_),
890 MetricsLogManager::ONGOING_LOG); 933 MetricsLogManager::ONGOING_LOG);
891 if (state_ == INITIALIZED) { 934 if (state_ == INITIALIZED) {
892 // We only need to schedule that run once. 935 // We only need to schedule that run once.
893 state_ = INIT_TASK_SCHEDULED; 936 state_ = INIT_TASK_SCHEDULED;
894 937
895 // Schedules a task on the file thread for execution of slower 938 // Schedules a delayed task for execution of slower initialization steps
896 // initialization steps (such as plugin list generation) necessary 939 // (such as plugin list generation) necessary for sending the initial log.
897 // for sending the initial log. This avoids blocking the main UI 940 MessageLoop::current()->PostDelayedTask(
898 // thread.
899 BrowserThread::PostDelayedTask(
900 BrowserThread::FILE,
901 FROM_HERE, 941 FROM_HERE,
902 base::Bind(&MetricsService::InitTaskGetHardwareClass, 942 base::Bind(&MetricsService::InitTaskGetHardwareClass,
903 self_ptr_factory_.GetWeakPtr(), 943 self_ptr_factory_.GetWeakPtr()),
904 MessageLoop::current()->message_loop_proxy()),
905 base::TimeDelta::FromSeconds(kInitializationDelaySeconds)); 944 base::TimeDelta::FromSeconds(kInitializationDelaySeconds));
906 } 945 }
907 } 946 }
908 947
909 void MetricsService::StopRecording() { 948 void MetricsService::StopRecording() {
910 if (!log_manager_.current_log()) 949 if (!log_manager_.current_log())
911 return; 950 return;
912 951
913 // TODO(jar): Integrate bounds on log recording more consistently, so that we 952 // TODO(jar): Integrate bounds on log recording more consistently, so that we
914 // can stop recording logs that are too big much sooner. 953 // can stop recording logs that are too big much sooner.
(...skipping 822 matching lines...) Expand 10 before | Expand all | Expand 10 after
1737 if (local_state) { 1776 if (local_state) {
1738 const PrefService::Preference* uma_pref = 1777 const PrefService::Preference* uma_pref =
1739 local_state->FindPreference(prefs::kMetricsReportingEnabled); 1778 local_state->FindPreference(prefs::kMetricsReportingEnabled);
1740 if (uma_pref) { 1779 if (uma_pref) {
1741 bool success = uma_pref->GetValue()->GetAsBoolean(&result); 1780 bool success = uma_pref->GetValue()->GetAsBoolean(&result);
1742 DCHECK(success); 1781 DCHECK(success);
1743 } 1782 }
1744 } 1783 }
1745 return result; 1784 return result;
1746 } 1785 }
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