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 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
175 #include "chrome/common/guid.h" | 175 #include "chrome/common/guid.h" |
176 #include "chrome/common/metrics/metrics_log_manager.h" | 176 #include "chrome/common/metrics/metrics_log_manager.h" |
177 #include "chrome/common/pref_names.h" | 177 #include "chrome/common/pref_names.h" |
178 #include "chrome/common/render_messages.h" | 178 #include "chrome/common/render_messages.h" |
179 #include "content/browser/load_notification_details.h" | 179 #include "content/browser/load_notification_details.h" |
180 #include "content/public/browser/child_process_data.h" | 180 #include "content/public/browser/child_process_data.h" |
181 #include "content/public/browser/notification_service.h" | 181 #include "content/public/browser/notification_service.h" |
182 #include "content/public/browser/plugin_service.h" | 182 #include "content/public/browser/plugin_service.h" |
183 #include "content/public/browser/render_process_host.h" | 183 #include "content/public/browser/render_process_host.h" |
184 #include "content/public/common/url_fetcher.h" | 184 #include "content/public/common/url_fetcher.h" |
185 #include "net/base/load_flags.h" | |
185 #include "webkit/plugins/webplugininfo.h" | 186 #include "webkit/plugins/webplugininfo.h" |
186 | 187 |
187 // TODO(port): port browser_distribution.h. | 188 // TODO(port): port browser_distribution.h. |
188 #if !defined(OS_POSIX) | 189 #if !defined(OS_POSIX) |
189 #include "chrome/installer/util/browser_distribution.h" | 190 #include "chrome/installer/util/browser_distribution.h" |
190 #endif | 191 #endif |
191 | 192 |
192 #if defined(OS_CHROMEOS) | 193 #if defined(OS_CHROMEOS) |
193 #include "chrome/browser/chromeos/cros/cros_library.h" | 194 #include "chrome/browser/chromeos/cros/cros_library.h" |
194 #include "chrome/browser/chromeos/external_metrics.h" | 195 #include "chrome/browser/chromeos/external_metrics.h" |
195 #include "chrome/browser/chromeos/system/statistics_provider.h" | 196 #include "chrome/browser/chromeos/system/statistics_provider.h" |
196 #endif | 197 #endif |
197 | 198 |
198 using base::Time; | 199 using base::Time; |
199 using content::BrowserThread; | 200 using content::BrowserThread; |
200 using content::ChildProcessData; | 201 using content::ChildProcessData; |
201 using content::PluginService; | 202 using content::PluginService; |
202 | 203 |
204 namespace { | |
205 | |
203 // Check to see that we're being called on only one thread. | 206 // Check to see that we're being called on only one thread. |
204 static bool IsSingleThreaded(); | 207 bool IsSingleThreaded() { |
208 static base::PlatformThreadId thread_id = 0; | |
209 if (!thread_id) | |
210 thread_id = base::PlatformThread::CurrentId(); | |
211 return base::PlatformThread::CurrentId() == thread_id; | |
212 } | |
205 | 213 |
206 static const char kMetricsType[] = "application/vnd.mozilla.metrics.bz2"; | 214 const char kMetricsTypeXml[] = "application/vnd.mozilla.metrics.bz2"; |
215 const char kMetricsTypeProto[] = "application/vnd.chrome.uma"; | |
216 | |
217 const char kServerUrlXml[] = | |
218 "https://clients4.google.com/firefox/metrics/collect"; | |
219 const char kServerUrlProto[] = "https://clients4.google.com/uma/v2"; | |
207 | 220 |
208 // The delay, in seconds, after starting recording before doing expensive | 221 // The delay, in seconds, after starting recording before doing expensive |
209 // initialization work. | 222 // initialization work. |
210 static const int kInitializationDelaySeconds = 30; | 223 const int kInitializationDelaySeconds = 30; |
Nico
2012/02/29 02:53:06
const has implicit internal linkage no need to mak
| |
211 | 224 |
212 // This specifies the amount of time to wait for all renderers to send their | 225 // This specifies the amount of time to wait for all renderers to send their |
213 // data. | 226 // data. |
214 static const int kMaxHistogramGatheringWaitDuration = 60000; // 60 seconds. | 227 const int kMaxHistogramGatheringWaitDuration = 60000; // 60 seconds. |
215 | 228 |
216 // The maximum number of events in a log uploaded to the UMA server. | 229 // The maximum number of events in a log uploaded to the UMA server. |
217 static const int kEventLimit = 2400; | 230 const int kEventLimit = 2400; |
218 | 231 |
219 // If an upload fails, and the transmission was over this byte count, then we | 232 // If an upload fails, and the transmission was over this byte count, then we |
220 // will discard the log, and not try to retransmit it. We also don't persist | 233 // will discard the log, and not try to retransmit it. We also don't persist |
221 // the log to the prefs for transmission during the next chrome session if this | 234 // the log to the prefs for transmission during the next chrome session if this |
222 // limit is exceeded. | 235 // limit is exceeded. |
223 static const int kUploadLogAvoidRetransmitSize = 50000; | 236 const size_t kUploadLogAvoidRetransmitSize = 50000; |
224 | 237 |
225 // Interval, in minutes, between state saves. | 238 // Interval, in minutes, between state saves. |
226 static const int kSaveStateIntervalMinutes = 5; | 239 const int kSaveStateIntervalMinutes = 5; |
240 | |
241 } | |
227 | 242 |
228 // static | 243 // static |
229 MetricsService::ShutdownCleanliness MetricsService::clean_shutdown_status_ = | 244 MetricsService::ShutdownCleanliness MetricsService::clean_shutdown_status_ = |
230 MetricsService::CLEANLY_SHUTDOWN; | 245 MetricsService::CLEANLY_SHUTDOWN; |
231 | 246 |
232 // This is used to quickly log stats from child process related notifications in | 247 // This is used to quickly log stats from child process related notifications in |
233 // MetricsService::child_stats_buffer_. The buffer's contents are transferred | 248 // MetricsService::child_stats_buffer_. The buffer's contents are transferred |
234 // out when Local State is periodically saved. The information is then | 249 // out when Local State is periodically saved. The information is then |
235 // reported to the UMA server on next launch. | 250 // reported to the UMA server on next launch. |
236 struct MetricsService::ChildProcessStats { | 251 struct MetricsService::ChildProcessStats { |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
316 0); | 331 0); |
317 #endif // OS_CHROMEOS | 332 #endif // OS_CHROMEOS |
318 | 333 |
319 local_state->RegisterDictionaryPref(prefs::kProfileMetrics); | 334 local_state->RegisterDictionaryPref(prefs::kProfileMetrics); |
320 local_state->RegisterIntegerPref(prefs::kNumBookmarksOnBookmarkBar, 0); | 335 local_state->RegisterIntegerPref(prefs::kNumBookmarksOnBookmarkBar, 0); |
321 local_state->RegisterIntegerPref(prefs::kNumFoldersOnBookmarkBar, 0); | 336 local_state->RegisterIntegerPref(prefs::kNumFoldersOnBookmarkBar, 0); |
322 local_state->RegisterIntegerPref(prefs::kNumBookmarksInOtherBookmarkFolder, | 337 local_state->RegisterIntegerPref(prefs::kNumBookmarksInOtherBookmarkFolder, |
323 0); | 338 0); |
324 local_state->RegisterIntegerPref(prefs::kNumFoldersInOtherBookmarkFolder, 0); | 339 local_state->RegisterIntegerPref(prefs::kNumFoldersInOtherBookmarkFolder, 0); |
325 local_state->RegisterIntegerPref(prefs::kNumKeywords, 0); | 340 local_state->RegisterIntegerPref(prefs::kNumKeywords, 0); |
326 local_state->RegisterListPref(prefs::kMetricsInitialLogs); | 341 local_state->RegisterListPref(prefs::kMetricsInitialLogsXml); |
327 local_state->RegisterListPref(prefs::kMetricsOngoingLogs); | 342 local_state->RegisterListPref(prefs::kMetricsOngoingLogsXml); |
343 local_state->RegisterListPref(prefs::kMetricsInitialLogsProto); | |
344 local_state->RegisterListPref(prefs::kMetricsOngoingLogsProto); | |
328 | 345 |
329 local_state->RegisterInt64Pref(prefs::kUninstallMetricsPageLoadCount, 0); | 346 local_state->RegisterInt64Pref(prefs::kUninstallMetricsPageLoadCount, 0); |
330 local_state->RegisterInt64Pref(prefs::kUninstallLaunchCount, 0); | 347 local_state->RegisterInt64Pref(prefs::kUninstallLaunchCount, 0); |
331 local_state->RegisterInt64Pref(prefs::kUninstallMetricsInstallDate, 0); | 348 local_state->RegisterInt64Pref(prefs::kUninstallMetricsInstallDate, 0); |
332 local_state->RegisterInt64Pref(prefs::kUninstallMetricsUptimeSec, 0); | 349 local_state->RegisterInt64Pref(prefs::kUninstallMetricsUptimeSec, 0); |
333 local_state->RegisterInt64Pref(prefs::kUninstallLastLaunchTimeSec, 0); | 350 local_state->RegisterInt64Pref(prefs::kUninstallLastLaunchTimeSec, 0); |
334 local_state->RegisterInt64Pref(prefs::kUninstallLastObservedRunTimeSec, 0); | 351 local_state->RegisterInt64Pref(prefs::kUninstallLastObservedRunTimeSec, 0); |
335 } | 352 } |
336 | 353 |
337 // static | 354 // static |
(...skipping 12 matching lines...) Expand all Loading... | |
350 | 367 |
351 local_state->SetInteger(prefs::kStabilityPageLoadCount, 0); | 368 local_state->SetInteger(prefs::kStabilityPageLoadCount, 0); |
352 local_state->SetInteger(prefs::kStabilityRendererCrashCount, 0); | 369 local_state->SetInteger(prefs::kStabilityRendererCrashCount, 0); |
353 local_state->SetInteger(prefs::kStabilityRendererHangCount, 0); | 370 local_state->SetInteger(prefs::kStabilityRendererHangCount, 0); |
354 | 371 |
355 local_state->SetInt64(prefs::kStabilityLaunchTimeSec, 0); | 372 local_state->SetInt64(prefs::kStabilityLaunchTimeSec, 0); |
356 local_state->SetInt64(prefs::kStabilityLastTimestampSec, 0); | 373 local_state->SetInt64(prefs::kStabilityLastTimestampSec, 0); |
357 | 374 |
358 local_state->ClearPref(prefs::kStabilityPluginStats); | 375 local_state->ClearPref(prefs::kStabilityPluginStats); |
359 | 376 |
360 local_state->ClearPref(prefs::kMetricsInitialLogs); | 377 local_state->ClearPref(prefs::kMetricsInitialLogsXml); |
361 local_state->ClearPref(prefs::kMetricsOngoingLogs); | 378 local_state->ClearPref(prefs::kMetricsOngoingLogsXml); |
379 local_state->ClearPref(prefs::kMetricsInitialLogsProto); | |
380 local_state->ClearPref(prefs::kMetricsOngoingLogsProto); | |
362 } | 381 } |
363 | 382 |
364 MetricsService::MetricsService() | 383 MetricsService::MetricsService() |
365 : recording_active_(false), | 384 : recording_active_(false), |
366 reporting_active_(false), | 385 reporting_active_(false), |
367 state_(INITIALIZED), | 386 state_(INITIALIZED), |
368 current_fetch_(NULL), | |
369 io_thread_(NULL), | 387 io_thread_(NULL), |
370 idle_since_last_transmission_(false), | 388 idle_since_last_transmission_(false), |
371 next_window_id_(0), | 389 next_window_id_(0), |
372 ALLOW_THIS_IN_INITIALIZER_LIST(self_ptr_factory_(this)), | 390 ALLOW_THIS_IN_INITIALIZER_LIST(self_ptr_factory_(this)), |
373 ALLOW_THIS_IN_INITIALIZER_LIST(state_saver_factory_(this)), | 391 ALLOW_THIS_IN_INITIALIZER_LIST(state_saver_factory_(this)), |
374 waiting_for_asynchronus_reporting_step_(false) { | 392 waiting_for_asynchronus_reporting_step_(false) { |
375 DCHECK(IsSingleThreaded()); | 393 DCHECK(IsSingleThreaded()); |
376 InitializeMetricsState(); | 394 InitializeMetricsState(); |
377 | 395 |
378 base::Closure callback = base::Bind(&MetricsService::StartScheduledUpload, | 396 base::Closure callback = base::Bind(&MetricsService::StartScheduledUpload, |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
621 //------------------------------------------------------------------------------ | 639 //------------------------------------------------------------------------------ |
622 // private methods | 640 // private methods |
623 //------------------------------------------------------------------------------ | 641 //------------------------------------------------------------------------------ |
624 | 642 |
625 | 643 |
626 //------------------------------------------------------------------------------ | 644 //------------------------------------------------------------------------------ |
627 // Initialization methods | 645 // Initialization methods |
628 | 646 |
629 void MetricsService::InitializeMetricsState() { | 647 void MetricsService::InitializeMetricsState() { |
630 #if defined(OS_POSIX) | 648 #if defined(OS_POSIX) |
631 server_url_ = L"https://clients4.google.com/firefox/metrics/collect"; | 649 server_url_xml_ = ASCIIToUTF16(kServerUrlXml); |
650 server_url_proto_ = ASCIIToUTF16(kServerUrlProto); | |
632 network_stats_server_ = "chrome.googleechotest.com"; | 651 network_stats_server_ = "chrome.googleechotest.com"; |
633 #else | 652 #else |
634 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); | 653 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
635 server_url_ = dist->GetStatsServerURL(); | 654 server_url_xml_ = dist->GetStatsServerURL(); |
655 server_url_proto_ = ASCIIToUTF16(kServerUrlProto); | |
636 network_stats_server_ = dist->GetNetworkStatsServer(); | 656 network_stats_server_ = dist->GetNetworkStatsServer(); |
637 #endif | 657 #endif |
638 | 658 |
639 PrefService* pref = g_browser_process->local_state(); | 659 PrefService* pref = g_browser_process->local_state(); |
640 DCHECK(pref); | 660 DCHECK(pref); |
641 | 661 |
642 if ((pref->GetInt64(prefs::kStabilityStatsBuildTime) | 662 if ((pref->GetInt64(prefs::kStabilityStatsBuildTime) |
643 != MetricsLog::GetBuildTime()) || | 663 != MetricsLog::GetBuildTime()) || |
644 (pref->GetString(prefs::kStabilityStatsVersion) | 664 (pref->GetString(prefs::kStabilityStatsVersion) |
645 != MetricsLog::GetVersionString())) { | 665 != MetricsLog::GetVersionString())) { |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
833 // Adds to ongoing logs. | 853 // Adds to ongoing logs. |
834 log_manager_.current_log()->set_hardware_class(hardware_class_); | 854 log_manager_.current_log()->set_hardware_class(hardware_class_); |
835 | 855 |
836 // Put incremental data (histogram deltas, and realtime stats deltas) at the | 856 // Put incremental data (histogram deltas, and realtime stats deltas) at the |
837 // end of all log transmissions (initial log handles this separately). | 857 // end of all log transmissions (initial log handles this separately). |
838 // RecordIncrementalStabilityElements only exists on the derived | 858 // RecordIncrementalStabilityElements only exists on the derived |
839 // MetricsLog class. | 859 // MetricsLog class. |
840 MetricsLog* current_log = | 860 MetricsLog* current_log = |
841 static_cast<MetricsLog*>(log_manager_.current_log()); | 861 static_cast<MetricsLog*>(log_manager_.current_log()); |
842 DCHECK(current_log); | 862 DCHECK(current_log); |
843 current_log->RecordIncrementalStabilityElements(); | 863 current_log->RecordIncrementalStabilityElements(plugins_); |
844 RecordCurrentHistograms(); | 864 RecordCurrentHistograms(); |
845 | 865 |
846 log_manager_.StageCurrentLogForUpload(); | 866 log_manager_.StageCurrentLogForUpload(); |
847 } | 867 } |
848 | 868 |
849 void MetricsService::PushPendingLogsToPersistentStorage() { | 869 void MetricsService::PushPendingLogsToPersistentStorage() { |
850 if (state_ < INITIAL_LOG_READY) | 870 if (state_ < INITIAL_LOG_READY) |
851 return; // We didn't and still don't have time to get plugin list etc. | 871 return; // We didn't and still don't have time to get plugin list etc. |
852 | 872 |
853 if (log_manager_.has_staged_log()) { | 873 if (log_manager_.has_staged_log()) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
928 MessageLoop::current(), callback, | 948 MessageLoop::current(), callback, |
929 kMaxHistogramGatheringWaitDuration); | 949 kMaxHistogramGatheringWaitDuration); |
930 } | 950 } |
931 | 951 |
932 void MetricsService::OnHistogramSynchronizationDone() { | 952 void MetricsService::OnHistogramSynchronizationDone() { |
933 DCHECK(IsSingleThreaded()); | 953 DCHECK(IsSingleThreaded()); |
934 | 954 |
935 // If somehow there is a fetch in progress, we return and hope things work | 955 // If somehow there is a fetch in progress, we return and hope things work |
936 // out. The scheduler isn't informed since if this happens, the scheduler | 956 // out. The scheduler isn't informed since if this happens, the scheduler |
937 // will get a response from the upload. | 957 // will get a response from the upload. |
938 DCHECK(!current_fetch_.get()); | 958 DCHECK(!current_fetch_xml_.get()); |
939 if (current_fetch_.get()) | 959 DCHECK(!current_fetch_proto_.get()); |
960 if (current_fetch_xml_.get() || current_fetch_proto_.get()) | |
940 return; | 961 return; |
941 | 962 |
942 // This function should only be called as the callback from an ansynchronous | 963 // This function should only be called as the callback from an ansynchronous |
943 // step. | 964 // step. |
944 DCHECK(waiting_for_asynchronus_reporting_step_); | 965 DCHECK(waiting_for_asynchronus_reporting_step_); |
945 waiting_for_asynchronus_reporting_step_ = false; | 966 waiting_for_asynchronus_reporting_step_ = false; |
946 | 967 |
947 // If we're getting no notifications, then the log won't have much in it, and | 968 // If we're getting no notifications, then the log won't have much in it, and |
948 // it's possible the computer is about to go to sleep, so don't upload and | 969 // it's possible the computer is about to go to sleep, so don't upload and |
949 // stop the scheduler. | 970 // stop the scheduler. |
950 // Similarly, if logs should no longer be uploaded, stop here. | 971 // Similarly, if logs should no longer be uploaded, stop here. |
951 if (idle_since_last_transmission_ || | 972 if (idle_since_last_transmission_ || |
952 !recording_active() || !reporting_active()) { | 973 !recording_active() || !reporting_active()) { |
953 scheduler_->Stop(); | 974 scheduler_->Stop(); |
954 scheduler_->UploadCancelled(); | 975 scheduler_->UploadCancelled(); |
955 return; | 976 return; |
956 } | 977 } |
957 | 978 |
958 MakeStagedLog(); | 979 MakeStagedLog(); |
959 | 980 |
960 // MakeStagedLog should have prepared log text; if it didn't, skip this | 981 // MakeStagedLog should have prepared log text; if it didn't, skip this |
961 // upload and hope things work out next time. | 982 // upload and hope things work out next time. |
962 if (log_manager_.staged_log_text().empty()) { | 983 if (log_manager_.staged_log_text().empty()) { |
963 scheduler_->UploadCancelled(); | 984 scheduler_->UploadCancelled(); |
964 return; | 985 return; |
965 } | 986 } |
966 | 987 |
967 PrepareFetchWithStagedLog(); | 988 PrepareFetchWithStagedLog(); |
968 | 989 |
969 if (!current_fetch_.get()) { | 990 if (!current_fetch_xml_.get()) { |
991 DCHECK(!current_fetch_proto_.get()); | |
970 // Compression failed, and log discarded :-/. | 992 // Compression failed, and log discarded :-/. |
971 log_manager_.DiscardStagedLog(); | 993 log_manager_.DiscardStagedLog(); |
972 scheduler_->UploadCancelled(); | 994 scheduler_->UploadCancelled(); |
973 // TODO(jar): If compression failed, we should have created a tiny log and | 995 // TODO(jar): If compression failed, we should have created a tiny log and |
974 // compressed that, so that we can signal that we're losing logs. | 996 // compressed that, so that we can signal that we're losing logs. |
975 return; | 997 return; |
976 } | 998 } |
999 // Currently, the staged log for the protobuf version of the data is discarded | |
1000 // after we create the URL request, so that there is no chance for | |
1001 // re-transmission in case the corresponding XML request fails. We will | |
1002 // handle protobuf failures more carefully once that becomes the main | |
1003 // pipeline, i.e. once we switch away from the XML pipeline. | |
1004 DCHECK(current_fetch_proto_.get() || !log_manager_.has_staged_log_proto()); | |
977 | 1005 |
978 DCHECK(!waiting_for_asynchronus_reporting_step_); | 1006 DCHECK(!waiting_for_asynchronus_reporting_step_); |
979 | 1007 |
980 waiting_for_asynchronus_reporting_step_ = true; | 1008 waiting_for_asynchronus_reporting_step_ = true; |
981 current_fetch_->Start(); | 1009 current_fetch_xml_->Start(); |
1010 if (current_fetch_proto_.get()) | |
1011 current_fetch_proto_->Start(); | |
982 | 1012 |
983 HandleIdleSinceLastTransmission(true); | 1013 HandleIdleSinceLastTransmission(true); |
984 } | 1014 } |
985 | 1015 |
986 | 1016 |
987 void MetricsService::MakeStagedLog() { | 1017 void MetricsService::MakeStagedLog() { |
988 if (log_manager_.has_staged_log()) | 1018 if (log_manager_.has_staged_log()) |
989 return; | 1019 return; |
990 | 1020 |
991 switch (state_) { | 1021 switch (state_) { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1045 | 1075 |
1046 void MetricsService::StoreUnsentLogs() { | 1076 void MetricsService::StoreUnsentLogs() { |
1047 if (state_ < INITIAL_LOG_READY) | 1077 if (state_ < INITIAL_LOG_READY) |
1048 return; // We never Recalled the prior unsent logs. | 1078 return; // We never Recalled the prior unsent logs. |
1049 | 1079 |
1050 log_manager_.PersistUnsentLogs(); | 1080 log_manager_.PersistUnsentLogs(); |
1051 } | 1081 } |
1052 | 1082 |
1053 void MetricsService::PrepareFetchWithStagedLog() { | 1083 void MetricsService::PrepareFetchWithStagedLog() { |
1054 DCHECK(!log_manager_.staged_log_text().empty()); | 1084 DCHECK(!log_manager_.staged_log_text().empty()); |
1055 DCHECK(!current_fetch_.get()); | |
1056 | 1085 |
1057 current_fetch_.reset(content::URLFetcher::Create( | 1086 // Prepare the XML version. |
1058 GURL(WideToUTF16(server_url_)), content::URLFetcher::POST, this)); | 1087 DCHECK(!current_fetch_xml_.get()); |
1059 current_fetch_->SetRequestContext( | 1088 current_fetch_xml_.reset(content::URLFetcher::Create( |
1089 GURL(server_url_xml_), content::URLFetcher::POST, this)); | |
1090 current_fetch_xml_->SetRequestContext( | |
1060 g_browser_process->system_request_context()); | 1091 g_browser_process->system_request_context()); |
1061 current_fetch_->SetUploadData(kMetricsType, log_manager_.staged_log_text()); | 1092 current_fetch_xml_->SetUploadData(kMetricsTypeXml, |
1093 log_manager_.staged_log_text().xml); | |
1094 // We already drop cookies server-side, but we might as well strip them out | |
1095 // client-side as well. | |
1096 current_fetch_xml_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | | |
1097 net::LOAD_DO_NOT_SEND_COOKIES); | |
1098 | |
1099 // Prepare the protobuf version. | |
1100 DCHECK(!current_fetch_proto_.get()); | |
1101 if (log_manager_.has_staged_log_proto()) { | |
1102 current_fetch_proto_.reset(content::URLFetcher::Create( | |
1103 GURL(server_url_proto_), content::URLFetcher::POST, this)); | |
1104 current_fetch_proto_->SetRequestContext( | |
1105 g_browser_process->system_request_context()); | |
1106 current_fetch_proto_->SetUploadData(kMetricsTypeProto, | |
1107 log_manager_.staged_log_text().proto); | |
1108 // We already drop cookies server-side, but we might as well strip them out | |
1109 // client-side as well. | |
1110 current_fetch_proto_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | | |
1111 net::LOAD_DO_NOT_SEND_COOKIES); | |
1112 | |
1113 // Discard the protobuf version of the staged log, so that we will avoid | |
1114 // re-uploading it even if we need to re-upload the XML version. | |
1115 // TODO(isherman): Handle protobuf upload failures more gracefully once we | |
1116 // transition away from the XML-based pipeline. | |
1117 log_manager_.DiscardStagedLogProto(); | |
1118 } | |
1062 } | 1119 } |
1063 | 1120 |
1064 static const char* StatusToString(const net::URLRequestStatus& status) { | 1121 static const char* StatusToString(const net::URLRequestStatus& status) { |
1065 switch (status.status()) { | 1122 switch (status.status()) { |
1066 case net::URLRequestStatus::SUCCESS: | 1123 case net::URLRequestStatus::SUCCESS: |
1067 return "SUCCESS"; | 1124 return "SUCCESS"; |
1068 | 1125 |
1069 case net::URLRequestStatus::IO_PENDING: | 1126 case net::URLRequestStatus::IO_PENDING: |
1070 return "IO_PENDING"; | 1127 return "IO_PENDING"; |
1071 | 1128 |
1072 case net::URLRequestStatus::HANDLED_EXTERNALLY: | 1129 case net::URLRequestStatus::HANDLED_EXTERNALLY: |
1073 return "HANDLED_EXTERNALLY"; | 1130 return "HANDLED_EXTERNALLY"; |
1074 | 1131 |
1075 case net::URLRequestStatus::CANCELED: | 1132 case net::URLRequestStatus::CANCELED: |
1076 return "CANCELED"; | 1133 return "CANCELED"; |
1077 | 1134 |
1078 case net::URLRequestStatus::FAILED: | 1135 case net::URLRequestStatus::FAILED: |
1079 return "FAILED"; | 1136 return "FAILED"; |
1080 | 1137 |
1081 default: | 1138 default: |
1082 NOTREACHED(); | 1139 NOTREACHED(); |
1083 return "Unknown"; | 1140 return "Unknown"; |
1084 } | 1141 } |
1085 } | 1142 } |
1086 | 1143 |
1144 // We need to wait for two responses: the response to the XML upload, and the | |
1145 // response to the protobuf upload. For now, only the XML upload's response | |
1146 // affects decisions like whether to retry the upload, whether to abandon the | |
1147 // upload because it is too large, etc. However, we still need to wait for the | |
1148 // protobuf upload, as we cannot reset |current_fetch_proto_| until we have | |
1149 // confirmation that the network request was sent; and the easiest way to do | |
1150 // that is to wait for the response. In case the XML upload's response arrives | |
1151 // first, we cache that response until the protobuf upload's response also | |
1152 // arrives. | |
1153 // | |
1154 // Note that if the XML upload succeeds but the protobuf upload fails, we will | |
1155 // not retry the protobuf upload. If the XML upload fails while the protobuf | |
1156 // upload succeeds, we will still avoid re-uploading the protobuf data because | |
1157 // we "zap" the data after the first upload attempt. This means that we might | |
1158 // lose protobuf uploads when XML ones succeed; but we will never duplicate any | |
1159 // protobuf uploads. Protobuf failures should be rare enough to where this | |
1160 // should be ok while we have the two pipelines running in parallel. | |
1087 void MetricsService::OnURLFetchComplete(const content::URLFetcher* source) { | 1161 void MetricsService::OnURLFetchComplete(const content::URLFetcher* source) { |
1088 DCHECK(waiting_for_asynchronus_reporting_step_); | 1162 DCHECK(waiting_for_asynchronus_reporting_step_); |
1163 | |
1164 // We're not allowed to re-use the existing |URLFetcher|s, so free them here. | |
1165 scoped_ptr<content::URLFetcher> s; | |
1166 if (source == current_fetch_xml_.get()) { | |
1167 s.reset(current_fetch_xml_.release()); | |
1168 | |
1169 // Cache the XML responses, in case we still need to wait for the protobuf | |
1170 // response. | |
1171 response_code_ = source->GetResponseCode(); | |
1172 response_status_ = StatusToString(source->GetStatus()); | |
1173 source->GetResponseAsString(&response_data_); | |
1174 } else if (source == current_fetch_proto_.get()) { | |
1175 s.reset(current_fetch_proto_.release()); | |
1176 } else { | |
1177 NOTREACHED(); | |
1178 return; | |
1179 } | |
1180 | |
1181 // If we're still waiting for one of the responses, keep waiting... | |
1182 if (current_fetch_xml_.get() || current_fetch_proto_.get()) | |
1183 return; | |
1184 | |
1185 // We should only be able to reach here once we've received responses to both | |
1186 // the XML and the protobuf requests. We should always have the response code | |
1187 // available. | |
1188 DCHECK_NE(response_code_, content::URLFetcher::RESPONSE_CODE_INVALID); | |
1089 waiting_for_asynchronus_reporting_step_ = false; | 1189 waiting_for_asynchronus_reporting_step_ = false; |
1090 DCHECK(current_fetch_.get()); | 1190 |
1091 // We're not allowed to re-use it. Delete it on function exit since we use it. | |
1092 scoped_ptr<content::URLFetcher> s(current_fetch_.release()); | |
1093 | 1191 |
1094 // Confirm send so that we can move on. | 1192 // Confirm send so that we can move on. |
1095 VLOG(1) << "METRICS RESPONSE CODE: " << source->GetResponseCode() | 1193 VLOG(1) << "METRICS RESPONSE CODE: " << response_code_ |
1096 << " status=" << StatusToString(source->GetStatus()); | 1194 << " status=" << response_status_; |
1097 | 1195 |
1098 bool upload_succeeded = source->GetResponseCode() == 200; | 1196 bool upload_succeeded = response_code_ == 200; |
1099 | 1197 |
1100 // Provide boolean for error recovery (allow us to ignore response_code). | 1198 // Provide boolean for error recovery (allow us to ignore response_code). |
1101 bool discard_log = false; | 1199 bool discard_log = false; |
1102 | 1200 |
1103 if (!upload_succeeded && | 1201 if (!upload_succeeded && |
1104 (log_manager_.staged_log_text().length() > | 1202 log_manager_.staged_log_text().xml.length() > |
1105 static_cast<size_t>(kUploadLogAvoidRetransmitSize))) { | 1203 kUploadLogAvoidRetransmitSize) { |
1106 UMA_HISTOGRAM_COUNTS( | 1204 UMA_HISTOGRAM_COUNTS( |
1107 "UMA.Large Rejected Log was Discarded", | 1205 "UMA.Large Rejected Log was Discarded", |
1108 static_cast<int>(log_manager_.staged_log_text().length())); | 1206 static_cast<int>(log_manager_.staged_log_text().xml.length())); |
1109 discard_log = true; | 1207 discard_log = true; |
1110 } else if (source->GetResponseCode() == 400) { | 1208 } else if (response_code_ == 400) { |
1111 // Bad syntax. Retransmission won't work. | 1209 // Bad syntax. Retransmission won't work. |
1112 UMA_HISTOGRAM_COUNTS("UMA.Unacceptable_Log_Discarded", state_); | 1210 UMA_HISTOGRAM_COUNTS("UMA.Unacceptable_Log_Discarded", state_); |
1113 discard_log = true; | 1211 discard_log = true; |
1114 } | 1212 } |
1115 | 1213 |
1116 if (!upload_succeeded && !discard_log) { | 1214 if (!upload_succeeded && !discard_log) { |
1117 VLOG(1) << "METRICS: transmission attempt returned a failure code: " | 1215 VLOG(1) << "METRICS: transmission attempt returned a failure code: " |
1118 << source->GetResponseCode() << ". Verify network connectivity"; | 1216 << response_code_ << ". Verify network connectivity"; |
1119 LogBadResponseCode(); | 1217 LogBadResponseCode(); |
1120 } else { // Successful receipt (or we are discarding log). | 1218 } else { // Successful receipt (or we are discarding log). |
1121 std::string data; | 1219 VLOG(1) << "METRICS RESPONSE DATA: " << response_data_; |
1122 source->GetResponseAsString(&data); | |
1123 VLOG(1) << "METRICS RESPONSE DATA: " << data; | |
1124 switch (state_) { | 1220 switch (state_) { |
1125 case INITIAL_LOG_READY: | 1221 case INITIAL_LOG_READY: |
1126 state_ = SENDING_OLD_LOGS; | 1222 state_ = SENDING_OLD_LOGS; |
1127 break; | 1223 break; |
1128 | 1224 |
1129 case SENDING_OLD_LOGS: | 1225 case SENDING_OLD_LOGS: |
1130 // Store the updated list to disk now that the removed log is uploaded. | 1226 // Store the updated list to disk now that the removed log is uploaded. |
1131 StoreUnsentLogs(); | 1227 StoreUnsentLogs(); |
1132 break; | 1228 break; |
1133 | 1229 |
1134 case SENDING_CURRENT_LOGS: | 1230 case SENDING_CURRENT_LOGS: |
1135 break; | 1231 break; |
1136 | 1232 |
1137 default: | 1233 default: |
1138 NOTREACHED(); | 1234 NOTREACHED(); |
1139 break; | 1235 break; |
1140 } | 1236 } |
1141 | 1237 |
1142 log_manager_.DiscardStagedLog(); | 1238 log_manager_.DiscardStagedLog(); |
1143 | 1239 |
1144 if (log_manager_.has_unsent_logs()) | 1240 if (log_manager_.has_unsent_logs()) |
1145 DCHECK(state_ < SENDING_CURRENT_LOGS); | 1241 DCHECK(state_ < SENDING_CURRENT_LOGS); |
1146 } | 1242 } |
1147 | 1243 |
1148 // Error 400 indicates a problem with the log, not with the server, so | 1244 // Error 400 indicates a problem with the log, not with the server, so |
1149 // don't consider that a sign that the server is in trouble. | 1245 // don't consider that a sign that the server is in trouble. |
1150 bool server_is_healthy = upload_succeeded || source->GetResponseCode() == 400; | 1246 bool server_is_healthy = upload_succeeded || response_code_ == 400; |
1151 | 1247 |
1152 scheduler_->UploadFinished(server_is_healthy, | 1248 scheduler_->UploadFinished(server_is_healthy, |
1153 log_manager_.has_unsent_logs()); | 1249 log_manager_.has_unsent_logs()); |
1154 | 1250 |
1155 // Collect network stats if UMA upload succeeded. | 1251 // Collect network stats if UMA upload succeeded. |
1156 if (server_is_healthy && io_thread_) | 1252 if (server_is_healthy && io_thread_) |
1157 chrome_browser_net::CollectNetworkStats(network_stats_server_, io_thread_); | 1253 chrome_browser_net::CollectNetworkStats(network_stats_server_, io_thread_); |
1254 | |
1255 // Reset the cached response data. | |
1256 response_code_ = content::URLFetcher::RESPONSE_CODE_INVALID; | |
1257 response_data_ = std::string(); | |
1258 response_status_ = std::string(); | |
1158 } | 1259 } |
1159 | 1260 |
1160 void MetricsService::LogBadResponseCode() { | 1261 void MetricsService::LogBadResponseCode() { |
1161 VLOG(1) << "Verify your metrics logs are formatted correctly. Verify server " | 1262 VLOG(1) << "Verify your metrics logs are formatted correctly. Verify server " |
1162 "is active at " << server_url_; | 1263 "is active at " << server_url_xml_; |
1163 if (!log_manager_.has_staged_log()) { | 1264 if (!log_manager_.has_staged_log()) { |
1164 VLOG(1) << "METRICS: Recorder shutdown during log transmission."; | 1265 VLOG(1) << "METRICS: Recorder shutdown during log transmission."; |
1165 } else { | 1266 } else { |
1166 VLOG(1) << "METRICS: transmission retry being scheduled for " | 1267 VLOG(1) << "METRICS: transmission retry being scheduled for " |
1167 << log_manager_.staged_log_text(); | 1268 << log_manager_.staged_log_text().xml; |
1168 } | 1269 } |
1169 } | 1270 } |
1170 | 1271 |
1171 void MetricsService::LogWindowChange( | 1272 void MetricsService::LogWindowChange( |
1172 int type, | 1273 int type, |
1173 const content::NotificationSource& source, | 1274 const content::NotificationSource& source, |
1174 const content::NotificationDetails& details) { | 1275 const content::NotificationDetails& details) { |
1175 int controller_id = -1; | 1276 int controller_id = -1; |
1176 uintptr_t window_or_tab = source.map_key(); | 1277 uintptr_t window_or_tab = source.map_key(); |
1177 MetricsLog::WindowEventType window_type; | 1278 MetricsLog::WindowEventType window_type; |
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1529 | 1630 |
1530 RecordPluginChanges(pref); | 1631 RecordPluginChanges(pref); |
1531 } | 1632 } |
1532 | 1633 |
1533 // static | 1634 // static |
1534 bool MetricsService::IsPluginProcess(content::ProcessType type) { | 1635 bool MetricsService::IsPluginProcess(content::ProcessType type) { |
1535 return (type == content::PROCESS_TYPE_PLUGIN|| | 1636 return (type == content::PROCESS_TYPE_PLUGIN|| |
1536 type == content::PROCESS_TYPE_PPAPI_PLUGIN); | 1637 type == content::PROCESS_TYPE_PPAPI_PLUGIN); |
1537 } | 1638 } |
1538 | 1639 |
1539 static bool IsSingleThreaded() { | |
1540 static base::PlatformThreadId thread_id = 0; | |
1541 if (!thread_id) | |
1542 thread_id = base::PlatformThread::CurrentId(); | |
1543 return base::PlatformThread::CurrentId() == thread_id; | |
1544 } | |
1545 | |
1546 #if defined(OS_CHROMEOS) | 1640 #if defined(OS_CHROMEOS) |
1547 void MetricsService::StartExternalMetrics() { | 1641 void MetricsService::StartExternalMetrics() { |
1548 external_metrics_ = new chromeos::ExternalMetrics; | 1642 external_metrics_ = new chromeos::ExternalMetrics; |
1549 external_metrics_->Start(); | 1643 external_metrics_->Start(); |
1550 } | 1644 } |
1551 #endif | 1645 #endif |
1552 | 1646 |
1553 // static | 1647 // static |
1554 bool MetricsServiceHelper::IsMetricsReportingEnabled() { | 1648 bool MetricsServiceHelper::IsMetricsReportingEnabled() { |
1555 bool result = false; | 1649 bool result = false; |
1556 const PrefService* local_state = g_browser_process->local_state(); | 1650 const PrefService* local_state = g_browser_process->local_state(); |
1557 if (local_state) { | 1651 if (local_state) { |
1558 const PrefService::Preference* uma_pref = | 1652 const PrefService::Preference* uma_pref = |
1559 local_state->FindPreference(prefs::kMetricsReportingEnabled); | 1653 local_state->FindPreference(prefs::kMetricsReportingEnabled); |
1560 if (uma_pref) { | 1654 if (uma_pref) { |
1561 bool success = uma_pref->GetValue()->GetAsBoolean(&result); | 1655 bool success = uma_pref->GetValue()->GetAsBoolean(&result); |
1562 DCHECK(success); | 1656 DCHECK(success); |
1563 } | 1657 } |
1564 } | 1658 } |
1565 return result; | 1659 return result; |
1566 } | 1660 } |
OLD | NEW |