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

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

Issue 9474041: Upload UMA data using protocol buffers. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix crash in test Created 8 years, 9 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 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698