OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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); | |
jar (doing other things)
2012/05/21 18:10:02
Are we sure it was added before we call this remov
Joao da Silva
2012/05/22 14:55:25
Removing an observer that isn't registered is OK.
| |
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 Loading... | |
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) |
768 // Exactly one of these two callbacks will be invoked. |on_timeout_callback_| | |
769 // is posted to UI with a certain delay; |on_ready_callback_| is invoked | |
770 // once the StatisticsProvider() becomes ready. Execution of one of these | |
771 // callbacks cancels the execution of the other. | |
772 on_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))); | |
778 | |
779 BrowserThread::PostDelayedTask( | |
780 BrowserThread::UI, FROM_HERE, | |
781 on_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); | |
jar (doing other things)
2012/05/21 18:10:02
I *think* the semantics of AddObserver() are such
| |
788 #else | |
789 InitTaskGetPluginInfo(); | |
790 #endif // OS_CHROMEOS | |
791 } | |
792 | |
793 #if defined(OS_CHROMEOS) | |
794 | |
795 void MetricsService::OnMachineStatisticsReady() { | |
796 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
761 chromeos::system::StatisticsProvider::GetInstance()->GetMachineStatistic( | 797 chromeos::system::StatisticsProvider::GetInstance()->GetMachineStatistic( |
762 "hardware_class", &hardware_class); | 798 "hardware_class", &hardware_class_); |
799 on_timeout_callback_.Cancel(); | |
800 if (!on_ready_callback_.IsCancelled()) | |
jar (doing other things)
2012/05/21 18:10:02
This cancellable callback looks more complex than
Joao da Silva
2012/05/22 14:55:25
That's another way to do it, I just wanted to avoi
jar (doing other things)
2012/05/22 17:07:58
Note: You could implement the "was_called" bool in
| |
801 on_ready_callback_.callback().Run(); | |
802 } | |
803 | |
804 void MetricsService::OnStatisticsProviderTimeout() { | |
805 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
806 // Use an invalid hardware_class temporarily until the StatisticsProvider is | |
807 // ready. | |
808 hardware_class_ = kHardwareClassNotReady; | |
809 on_ready_callback_.Cancel(); | |
810 InitTaskGetPluginInfo(); | |
811 } | |
812 | |
763 #endif // OS_CHROMEOS | 813 #endif // OS_CHROMEOS |
764 | 814 |
765 target_loop->PostTask(FROM_HERE, | 815 void MetricsService::InitTaskGetPluginInfo() { |
766 base::Bind(&MetricsService::OnInitTaskGotHardwareClass, | 816 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
767 self, hardware_class)); | |
768 } | |
769 | |
770 void MetricsService::OnInitTaskGotHardwareClass( | |
771 const std::string& hardware_class) { | |
772 DCHECK_EQ(INIT_TASK_SCHEDULED, state_); | 817 DCHECK_EQ(INIT_TASK_SCHEDULED, state_); |
773 hardware_class_ = hardware_class; | |
774 | 818 |
775 // Start the next part of the init task: loading plugin information. | 819 // Start the next part of the init task: loading plugin information. |
776 PluginService::GetInstance()->GetPlugins( | 820 PluginService::GetInstance()->GetPlugins( |
777 base::Bind(&MetricsService::OnInitTaskGotPluginInfo, | 821 base::Bind(&MetricsService::OnInitTaskGotPluginInfo, |
778 self_ptr_factory_.GetWeakPtr())); | 822 self_ptr_factory_.GetWeakPtr())); |
779 } | 823 } |
780 | 824 |
781 void MetricsService::OnInitTaskGotPluginInfo( | 825 void MetricsService::OnInitTaskGotPluginInfo( |
782 const std::vector<webkit::WebPluginInfo>& plugins) { | 826 const std::vector<webkit::WebPluginInfo>& plugins) { |
783 DCHECK_EQ(INIT_TASK_SCHEDULED, state_); | 827 DCHECK_EQ(INIT_TASK_SCHEDULED, state_); |
784 plugins_ = plugins; | 828 plugins_ = plugins; |
785 | 829 |
786 // Schedules a task on a blocking pool thread to gather Google Update | 830 // Schedules a task on a blocking pool thread to gather Google Update |
787 // statistics (requires Registry reads). | 831 // statistics (requires Registry reads). |
788 BrowserThread::PostBlockingPoolTask( | 832 BrowserThread::PostBlockingPoolTask( |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
885 void MetricsService::StartRecording() { | 929 void MetricsService::StartRecording() { |
886 if (log_manager_.current_log()) | 930 if (log_manager_.current_log()) |
887 return; | 931 return; |
888 | 932 |
889 log_manager_.BeginLoggingWithLog(new MetricsLog(client_id_, session_id_), | 933 log_manager_.BeginLoggingWithLog(new MetricsLog(client_id_, session_id_), |
890 MetricsLogManager::ONGOING_LOG); | 934 MetricsLogManager::ONGOING_LOG); |
891 if (state_ == INITIALIZED) { | 935 if (state_ == INITIALIZED) { |
892 // We only need to schedule that run once. | 936 // We only need to schedule that run once. |
893 state_ = INIT_TASK_SCHEDULED; | 937 state_ = INIT_TASK_SCHEDULED; |
894 | 938 |
895 // Schedules a task on the file thread for execution of slower | 939 // Schedules a delayed task for execution of slower initialization steps |
896 // initialization steps (such as plugin list generation) necessary | 940 // (such as plugin list generation) necessary for sending the initial log. |
897 // for sending the initial log. This avoids blocking the main UI | 941 MessageLoop::current()->PostDelayedTask( |
jar (doing other things)
2012/05/21 18:10:02
Why are we now willing to do this on the current (
Joao da Silva
2012/05/22 14:55:25
Because this isn't a blocking operation anymore, i
jar (doing other things)
2012/05/22 17:07:58
Since it is non-blocking, there should be even les
Joao da Silva
2012/05/22 19:10:09
I may be misunderstanding, but that is the case. T
| |
898 // thread. | |
899 BrowserThread::PostDelayedTask( | |
900 BrowserThread::FILE, | |
901 FROM_HERE, | 942 FROM_HERE, |
902 base::Bind(&MetricsService::InitTaskGetHardwareClass, | 943 base::Bind(&MetricsService::InitTaskGetHardwareClass, |
903 self_ptr_factory_.GetWeakPtr(), | 944 self_ptr_factory_.GetWeakPtr()), |
904 MessageLoop::current()->message_loop_proxy()), | |
905 base::TimeDelta::FromSeconds(kInitializationDelaySeconds)); | 945 base::TimeDelta::FromSeconds(kInitializationDelaySeconds)); |
906 } | 946 } |
907 } | 947 } |
908 | 948 |
909 void MetricsService::StopRecording() { | 949 void MetricsService::StopRecording() { |
910 if (!log_manager_.current_log()) | 950 if (!log_manager_.current_log()) |
911 return; | 951 return; |
912 | 952 |
913 // TODO(jar): Integrate bounds on log recording more consistently, so that we | 953 // TODO(jar): Integrate bounds on log recording more consistently, so that we |
914 // can stop recording logs that are too big much sooner. | 954 // can stop recording logs that are too big much sooner. |
(...skipping 822 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1737 if (local_state) { | 1777 if (local_state) { |
1738 const PrefService::Preference* uma_pref = | 1778 const PrefService::Preference* uma_pref = |
1739 local_state->FindPreference(prefs::kMetricsReportingEnabled); | 1779 local_state->FindPreference(prefs::kMetricsReportingEnabled); |
1740 if (uma_pref) { | 1780 if (uma_pref) { |
1741 bool success = uma_pref->GetValue()->GetAsBoolean(&result); | 1781 bool success = uma_pref->GetValue()->GetAsBoolean(&result); |
1742 DCHECK(success); | 1782 DCHECK(success); |
1743 } | 1783 } |
1744 } | 1784 } |
1745 return result; | 1785 return result; |
1746 } | 1786 } |
OLD | NEW |