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

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

Issue 9396001: Begin to separate the MetricsService logic for creating vs uploading logs (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address review comments 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 800 matching lines...) Expand 10 before | Expand all | Expand 10 after
811 } 811 }
812 812
813 813
814 //------------------------------------------------------------------------------ 814 //------------------------------------------------------------------------------
815 // Recording control methods 815 // Recording control methods
816 816
817 void MetricsService::StartRecording() { 817 void MetricsService::StartRecording() {
818 if (log_manager_.current_log()) 818 if (log_manager_.current_log())
819 return; 819 return;
820 820
821 log_manager_.BeginLoggingWithLog(new MetricsLog(client_id_, session_id_)); 821 log_manager_.BeginLoggingWithLog(new MetricsLog(client_id_, session_id_),
822 MetricsLogManager::ONGOING_LOG);
822 if (state_ == INITIALIZED) { 823 if (state_ == INITIALIZED) {
823 // We only need to schedule that run once. 824 // We only need to schedule that run once.
824 state_ = INIT_TASK_SCHEDULED; 825 state_ = INIT_TASK_SCHEDULED;
825 826
826 // Schedules a task on the file thread for execution of slower 827 // Schedules a task on the file thread for execution of slower
827 // initialization steps (such as plugin list generation) necessary 828 // initialization steps (such as plugin list generation) necessary
828 // for sending the initial log. This avoids blocking the main UI 829 // for sending the initial log. This avoids blocking the main UI
829 // thread. 830 // thread.
830 BrowserThread::PostDelayedTask( 831 BrowserThread::PostDelayedTask(
831 BrowserThread::FILE, 832 BrowserThread::FILE,
(...skipping 24 matching lines...) Expand all
856 // Put incremental data (histogram deltas, and realtime stats deltas) at the 857 // Put incremental data (histogram deltas, and realtime stats deltas) at the
857 // end of all log transmissions (initial log handles this separately). 858 // end of all log transmissions (initial log handles this separately).
858 // RecordIncrementalStabilityElements only exists on the derived 859 // RecordIncrementalStabilityElements only exists on the derived
859 // MetricsLog class. 860 // MetricsLog class.
860 MetricsLog* current_log = 861 MetricsLog* current_log =
861 static_cast<MetricsLog*>(log_manager_.current_log()); 862 static_cast<MetricsLog*>(log_manager_.current_log());
862 DCHECK(current_log); 863 DCHECK(current_log);
863 current_log->RecordIncrementalStabilityElements(plugins_); 864 current_log->RecordIncrementalStabilityElements(plugins_);
864 RecordCurrentHistograms(); 865 RecordCurrentHistograms();
865 866
866 log_manager_.StageCurrentLogForUpload(); 867 log_manager_.FinishCurrentLog();
867 } 868 }
868 869
869 void MetricsService::PushPendingLogsToPersistentStorage() { 870 void MetricsService::PushPendingLogsToPersistentStorage() {
870 if (state_ < INITIAL_LOG_READY) 871 if (state_ < INITIAL_LOG_READY)
871 return; // We didn't and still don't have time to get plugin list etc. 872 return; // We didn't and still don't have time to get plugin list etc.
872 873
873 if (log_manager_.has_staged_log()) { 874 if (log_manager_.has_staged_log()) {
874 if (state_ == INITIAL_LOG_READY) { 875 // We may race here, and send second copy of initial log later.
875 // We may race here, and send second copy of initial log later. 876 if (state_ == INITIAL_LOG_READY)
876 log_manager_.StoreStagedLogAsUnsent(MetricsLogManager::INITIAL_LOG);
877 state_ = SENDING_OLD_LOGS; 877 state_ = SENDING_OLD_LOGS;
878 } else { 878 log_manager_.StoreStagedLogAsUnsent();
879 // TODO(jar): Verify correctness in other states, including sending unsent
880 // initial logs.
881 log_manager_.StoreStagedLogAsUnsent(MetricsLogManager::ONGOING_LOG);
882 }
883 } 879 }
884 DCHECK(!log_manager_.has_staged_log()); 880 DCHECK(!log_manager_.has_staged_log());
885 StopRecording(); 881 StopRecording();
886 log_manager_.StoreStagedLogAsUnsent(MetricsLogManager::ONGOING_LOG);
887 StoreUnsentLogs(); 882 StoreUnsentLogs();
888 } 883 }
889 884
890 //------------------------------------------------------------------------------ 885 //------------------------------------------------------------------------------
891 // Transmission of logs methods 886 // Transmission of logs methods
892 887
893 void MetricsService::StartSchedulerIfNecessary() { 888 void MetricsService::StartSchedulerIfNecessary() {
894 if (reporting_active() && recording_active()) 889 if (reporting_active() && recording_active())
895 scheduler_->Start(); 890 scheduler_->Start();
896 } 891 }
897 892
898 void MetricsService::StartScheduledUpload() { 893 void MetricsService::StartScheduledUpload() {
899 // If reporting has been turned off, the scheduler doesn't need to run. 894 // If reporting has been turned off, the scheduler doesn't need to run.
900 if (!reporting_active() || !recording_active()) { 895 if (!reporting_active() || !recording_active()) {
901 scheduler_->Stop(); 896 scheduler_->Stop();
902 scheduler_->UploadCancelled(); 897 scheduler_->UploadCancelled();
903 return; 898 return;
904 } 899 }
905 900
901 StartFinalLogInfoCollection();
902 }
903
904 void MetricsService::StartFinalLogInfoCollection() {
905 // Begin the multi-step process of collecting memory usage histograms:
906 // First spawn a task to collect the memory details; when that task is
907 // finished, it will call OnMemoryDetailCollectionDone. That will in turn
908 // call HistogramSynchronization to collect histograms from all renderers and
909 // then call OnHistogramSynchronizationDone to continue processing.
906 DCHECK(!waiting_for_asynchronus_reporting_step_); 910 DCHECK(!waiting_for_asynchronus_reporting_step_);
907 waiting_for_asynchronus_reporting_step_ = true; 911 waiting_for_asynchronus_reporting_step_ = true;
908 912
909 base::Closure callback = 913 base::Closure callback =
910 base::Bind(&MetricsService::OnMemoryDetailCollectionDone, 914 base::Bind(&MetricsService::OnMemoryDetailCollectionDone,
911 self_ptr_factory_.GetWeakPtr()); 915 self_ptr_factory_.GetWeakPtr());
912 916
913 scoped_refptr<MetricsMemoryDetails> details( 917 scoped_refptr<MetricsMemoryDetails> details(
914 new MetricsMemoryDetails(callback)); 918 new MetricsMemoryDetails(callback));
915 details->StartFetch(); 919 details->StartFetch();
916 920
917 // Collect WebCore cache information to put into a histogram. 921 // Collect WebCore cache information to put into a histogram.
918 for (content::RenderProcessHost::iterator i( 922 for (content::RenderProcessHost::iterator i(
919 content::RenderProcessHost::AllHostsIterator()); 923 content::RenderProcessHost::AllHostsIterator());
920 !i.IsAtEnd(); i.Advance()) 924 !i.IsAtEnd(); i.Advance())
921 i.GetCurrentValue()->Send(new ChromeViewMsg_GetCacheResourceStats()); 925 i.GetCurrentValue()->Send(new ChromeViewMsg_GetCacheResourceStats());
922 } 926 }
923 927
924 void MetricsService::OnMemoryDetailCollectionDone() { 928 void MetricsService::OnMemoryDetailCollectionDone() {
925 DCHECK(IsSingleThreaded()); 929 DCHECK(IsSingleThreaded());
926 // This function should only be called as the callback from an ansynchronous 930 // This function should only be called as the callback from an ansynchronous
927 // step. 931 // step.
928 DCHECK(waiting_for_asynchronus_reporting_step_); 932 DCHECK(waiting_for_asynchronus_reporting_step_);
929 933
930 // Right before the UMA transmission gets started, there's one more thing we'd
931 // like to record: the histogram of memory usage, so we spawn a task to
932 // collect the memory details and when that task is finished, it will call
933 // OnMemoryDetailCollectionDone, which will call HistogramSynchronization to
934 // collect histograms from all renderers and then we will call
935 // OnHistogramSynchronizationDone to continue processing.
936
937 // Create a callback_task for OnHistogramSynchronizationDone. 934 // Create a callback_task for OnHistogramSynchronizationDone.
938 base::Closure callback = base::Bind( 935 base::Closure callback = base::Bind(
939 &MetricsService::OnHistogramSynchronizationDone, 936 &MetricsService::OnHistogramSynchronizationDone,
940 self_ptr_factory_.GetWeakPtr()); 937 self_ptr_factory_.GetWeakPtr());
941 938
942 base::StatisticsRecorder::CollectHistogramStats("Browser"); 939 base::StatisticsRecorder::CollectHistogramStats("Browser");
943 940
944 // Set up the callback to task to call after we receive histograms from all 941 // Set up the callback to task to call after we receive histograms from all
945 // renderer processes. Wait time specifies how long to wait before absolutely 942 // renderer processes. Wait time specifies how long to wait before absolutely
946 // calling us back on the task. 943 // calling us back on the task.
947 HistogramSynchronizer::FetchRendererHistogramsAsynchronously( 944 HistogramSynchronizer::FetchRendererHistogramsAsynchronously(
948 MessageLoop::current(), callback, 945 MessageLoop::current(), callback,
949 kMaxHistogramGatheringWaitDuration); 946 kMaxHistogramGatheringWaitDuration);
950 } 947 }
951 948
952 void MetricsService::OnHistogramSynchronizationDone() { 949 void MetricsService::OnHistogramSynchronizationDone() {
953 DCHECK(IsSingleThreaded()); 950 DCHECK(IsSingleThreaded());
951 // This function should only be called as the callback from an ansynchronous
952 // step.
953 DCHECK(waiting_for_asynchronus_reporting_step_);
954 954
955 waiting_for_asynchronus_reporting_step_ = false;
956 OnFinalLogInfoCollectionDone();
957 }
958
959 void MetricsService::OnFinalLogInfoCollectionDone() {
955 // If somehow there is a fetch in progress, we return and hope things work 960 // If somehow there is a fetch in progress, we return and hope things work
956 // out. The scheduler isn't informed since if this happens, the scheduler 961 // out. The scheduler isn't informed since if this happens, the scheduler
957 // will get a response from the upload. 962 // will get a response from the upload.
958 DCHECK(!current_fetch_xml_.get()); 963 DCHECK(!current_fetch_xml_.get());
959 DCHECK(!current_fetch_proto_.get()); 964 DCHECK(!current_fetch_proto_.get());
960 if (current_fetch_xml_.get() || current_fetch_proto_.get()) 965 if (current_fetch_xml_.get() || current_fetch_proto_.get())
961 return; 966 return;
962 967
963 // This function should only be called as the callback from an ansynchronous
964 // step.
965 DCHECK(waiting_for_asynchronus_reporting_step_);
966 waiting_for_asynchronus_reporting_step_ = false;
967
968 // 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
969 // 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
970 // stop the scheduler. 970 // stop the scheduler.
971 // Similarly, if logs should no longer be uploaded, stop here. 971 // Similarly, if logs should no longer be uploaded, stop here.
972 if (idle_since_last_transmission_ || 972 if (idle_since_last_transmission_ ||
973 !recording_active() || !reporting_active()) { 973 !recording_active() || !reporting_active()) {
974 scheduler_->Stop(); 974 scheduler_->Stop();
975 scheduler_->UploadCancelled(); 975 scheduler_->UploadCancelled();
976 return; 976 return;
977 } 977 }
978 978
979 MakeStagedLog(); 979 MakeStagedLog();
980 980
981 // 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
982 // upload and hope things work out next time. 982 // upload and hope things work out next time.
983 if (log_manager_.staged_log_text().empty()) { 983 if (log_manager_.staged_log_text().empty()) {
984 scheduler_->UploadCancelled(); 984 scheduler_->UploadCancelled();
985 return; 985 return;
986 } 986 }
987 987
988 PrepareFetchWithStagedLog(); 988 SendStagedLog();
989
990 if (!current_fetch_xml_.get()) {
991 DCHECK(!current_fetch_proto_.get());
992 // Compression failed, and log discarded :-/.
993 log_manager_.DiscardStagedLog();
994 scheduler_->UploadCancelled();
995 // TODO(jar): If compression failed, we should have created a tiny log and
996 // compressed that, so that we can signal that we're losing logs.
997 return;
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());
1005
1006 DCHECK(!waiting_for_asynchronus_reporting_step_);
1007
1008 waiting_for_asynchronus_reporting_step_ = true;
1009 current_fetch_xml_->Start();
1010 if (current_fetch_proto_.get())
1011 current_fetch_proto_->Start();
1012
1013 HandleIdleSinceLastTransmission(true);
1014 } 989 }
1015 990
1016
1017 void MetricsService::MakeStagedLog() { 991 void MetricsService::MakeStagedLog() {
1018 if (log_manager_.has_staged_log()) 992 if (log_manager_.has_staged_log())
1019 return; 993 return;
1020 994
1021 switch (state_) { 995 switch (state_) {
1022 case INITIALIZED: 996 case INITIALIZED:
1023 case INIT_TASK_SCHEDULED: // We should be further along by now. 997 case INIT_TASK_SCHEDULED: // We should be further along by now.
1024 DCHECK(false); 998 DCHECK(false);
1025 return; 999 return;
1026 1000
1027 case INIT_TASK_DONE: 1001 case INIT_TASK_DONE:
1028 // We need to wait for the initial log to be ready before sending 1002 // We need to wait for the initial log to be ready before sending
1029 // anything, because the server will tell us whether it wants to hear 1003 // anything, because the server will tell us whether it wants to hear
1030 // from us. 1004 // from us.
1031 PrepareInitialLog(); 1005 PrepareInitialLog();
1032 DCHECK(state_ == INIT_TASK_DONE); 1006 DCHECK(state_ == INIT_TASK_DONE);
1033 log_manager_.LoadPersistedUnsentLogs(); 1007 log_manager_.LoadPersistedUnsentLogs();
1034 state_ = INITIAL_LOG_READY; 1008 state_ = INITIAL_LOG_READY;
1035 break; 1009 break;
1036 1010
1037 case SENDING_OLD_LOGS: 1011 case SENDING_OLD_LOGS:
1038 if (log_manager_.has_unsent_logs()) { 1012 if (log_manager_.has_unsent_logs()) {
1039 log_manager_.StageNextStoredLogForUpload(); 1013 log_manager_.StageNextLogForUpload();
1040 break; 1014 break;
1041 } 1015 }
1042 state_ = SENDING_CURRENT_LOGS; 1016 state_ = SENDING_CURRENT_LOGS;
1043 // Fall through. 1017 // Fall through.
1044 1018
1045 case SENDING_CURRENT_LOGS: 1019 case SENDING_CURRENT_LOGS:
1046 StopRecording(); 1020 StopRecording();
1047 StartRecording(); 1021 StartRecording();
1022 log_manager_.StageNextLogForUpload();
1048 break; 1023 break;
1049 1024
1050 default: 1025 default:
1051 NOTREACHED(); 1026 NOTREACHED();
1052 return; 1027 return;
1053 } 1028 }
1054 1029
1055 DCHECK(log_manager_.has_staged_log()); 1030 DCHECK(log_manager_.has_staged_log());
1056 } 1031 }
1057 1032
1058 void MetricsService::PrepareInitialLog() { 1033 void MetricsService::PrepareInitialLog() {
1059 DCHECK(state_ == INIT_TASK_DONE); 1034 DCHECK(state_ == INIT_TASK_DONE);
1060 1035
1061 MetricsLog* log = new MetricsLog(client_id_, session_id_); 1036 MetricsLog* log = new MetricsLog(client_id_, session_id_);
1062 log->set_hardware_class(hardware_class_); // Adds to initial log. 1037 log->set_hardware_class(hardware_class_); // Adds to initial log.
1063 log->RecordEnvironment(plugins_, profile_dictionary_.get()); 1038 log->RecordEnvironment(plugins_, profile_dictionary_.get());
1064 1039
1065 // Histograms only get written to the current log, so make the new log current 1040 // Histograms only get written to the current log, so make the new log current
1066 // before writing them. 1041 // before writing them.
1067 log_manager_.PauseCurrentLog(); 1042 log_manager_.PauseCurrentLog();
1068 log_manager_.BeginLoggingWithLog(log); 1043 log_manager_.BeginLoggingWithLog(log, MetricsLogManager::INITIAL_LOG);
1069 RecordCurrentHistograms(); 1044 RecordCurrentHistograms();
1045 log_manager_.FinishCurrentLog();
1046 log_manager_.ResumePausedLog();
1070 1047
1071 DCHECK(!log_manager_.has_staged_log()); 1048 DCHECK(!log_manager_.has_staged_log());
1072 log_manager_.StageCurrentLogForUpload(); 1049 log_manager_.StageNextLogForUpload();
1073 log_manager_.ResumePausedLog();
1074 } 1050 }
1075 1051
1076 void MetricsService::StoreUnsentLogs() { 1052 void MetricsService::StoreUnsentLogs() {
1077 if (state_ < INITIAL_LOG_READY) 1053 if (state_ < INITIAL_LOG_READY)
1078 return; // We never Recalled the prior unsent logs. 1054 return; // We never Recalled the prior unsent logs.
1079 1055
1080 log_manager_.PersistUnsentLogs(); 1056 log_manager_.PersistUnsentLogs();
1081 } 1057 }
1082 1058
1059 void MetricsService::SendStagedLog() {
1060 DCHECK(log_manager_.has_staged_log());
1061
1062 PrepareFetchWithStagedLog();
1063
1064 if (!current_fetch_xml_.get()) {
1065 DCHECK(!current_fetch_proto_.get());
1066 // Compression failed, and log discarded :-/.
1067 log_manager_.DiscardStagedLog();
1068 scheduler_->UploadCancelled();
1069 // TODO(jar): If compression failed, we should have created a tiny log and
1070 // compressed that, so that we can signal that we're losing logs.
1071 return;
1072 }
1073 // Currently, the staged log for the protobuf version of the data is discarded
1074 // after we create the URL request, so that there is no chance for
1075 // re-transmission in case the corresponding XML request fails. We will
1076 // handle protobuf failures more carefully once that becomes the main
1077 // pipeline, i.e. once we switch away from the XML pipeline.
1078 DCHECK(current_fetch_proto_.get() || !log_manager_.has_staged_log_proto());
1079
1080 DCHECK(!waiting_for_asynchronus_reporting_step_);
1081
1082 waiting_for_asynchronus_reporting_step_ = true;
1083 current_fetch_xml_->Start();
1084 if (current_fetch_proto_.get())
1085 current_fetch_proto_->Start();
1086
1087 HandleIdleSinceLastTransmission(true);
1088 }
1089
1083 void MetricsService::PrepareFetchWithStagedLog() { 1090 void MetricsService::PrepareFetchWithStagedLog() {
1084 DCHECK(!log_manager_.staged_log_text().empty()); 1091 DCHECK(!log_manager_.staged_log_text().empty());
1085 1092
1086 // Prepare the XML version. 1093 // Prepare the XML version.
1087 DCHECK(!current_fetch_xml_.get()); 1094 DCHECK(!current_fetch_xml_.get());
1088 current_fetch_xml_.reset(content::URLFetcher::Create( 1095 current_fetch_xml_.reset(content::URLFetcher::Create(
1089 GURL(server_url_xml_), content::URLFetcher::POST, this)); 1096 GURL(server_url_xml_), content::URLFetcher::POST, this));
1090 current_fetch_xml_->SetRequestContext( 1097 current_fetch_xml_->SetRequestContext(
1091 g_browser_process->system_request_context()); 1098 g_browser_process->system_request_context());
1092 current_fetch_xml_->SetUploadData(kMetricsTypeXml, 1099 current_fetch_xml_->SetUploadData(kMetricsTypeXml,
(...skipping 558 matching lines...) Expand 10 before | Expand all | Expand 10 after
1651 if (local_state) { 1658 if (local_state) {
1652 const PrefService::Preference* uma_pref = 1659 const PrefService::Preference* uma_pref =
1653 local_state->FindPreference(prefs::kMetricsReportingEnabled); 1660 local_state->FindPreference(prefs::kMetricsReportingEnabled);
1654 if (uma_pref) { 1661 if (uma_pref) {
1655 bool success = uma_pref->GetValue()->GetAsBoolean(&result); 1662 bool success = uma_pref->GetValue()->GetAsBoolean(&result);
1656 DCHECK(success); 1663 DCHECK(success);
1657 } 1664 }
1658 } 1665 }
1659 return result; 1666 return result;
1660 } 1667 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698