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

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: Created 8 years, 10 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 779 matching lines...) Expand 10 before | Expand all | Expand 10 after
790 } 790 }
791 791
792 792
793 //------------------------------------------------------------------------------ 793 //------------------------------------------------------------------------------
794 // Recording control methods 794 // Recording control methods
795 795
796 void MetricsService::StartRecording() { 796 void MetricsService::StartRecording() {
797 if (log_manager_.current_log()) 797 if (log_manager_.current_log())
798 return; 798 return;
799 799
800 log_manager_.BeginLoggingWithLog(new MetricsLog(client_id_, session_id_)); 800 log_manager_.BeginLoggingWithLog(new MetricsLog(client_id_, session_id_),
801 MetricsLogManager::ONGOING_LOG);
801 if (state_ == INITIALIZED) { 802 if (state_ == INITIALIZED) {
802 // We only need to schedule that run once. 803 // We only need to schedule that run once.
803 state_ = INIT_TASK_SCHEDULED; 804 state_ = INIT_TASK_SCHEDULED;
804 805
805 // Schedules a task on the file thread for execution of slower 806 // Schedules a task on the file thread for execution of slower
806 // initialization steps (such as plugin list generation) necessary 807 // initialization steps (such as plugin list generation) necessary
807 // for sending the initial log. This avoids blocking the main UI 808 // for sending the initial log. This avoids blocking the main UI
808 // thread. 809 // thread.
809 BrowserThread::PostDelayedTask( 810 BrowserThread::PostDelayedTask(
810 BrowserThread::FILE, 811 BrowserThread::FILE,
(...skipping 24 matching lines...) Expand all
835 // Put incremental data (histogram deltas, and realtime stats deltas) at the 836 // Put incremental data (histogram deltas, and realtime stats deltas) at the
836 // end of all log transmissions (initial log handles this separately). 837 // end of all log transmissions (initial log handles this separately).
837 // RecordIncrementalStabilityElements only exists on the derived 838 // RecordIncrementalStabilityElements only exists on the derived
838 // MetricsLog class. 839 // MetricsLog class.
839 MetricsLog* current_log = 840 MetricsLog* current_log =
840 static_cast<MetricsLog*>(log_manager_.current_log()); 841 static_cast<MetricsLog*>(log_manager_.current_log());
841 DCHECK(current_log); 842 DCHECK(current_log);
842 current_log->RecordIncrementalStabilityElements(); 843 current_log->RecordIncrementalStabilityElements();
843 RecordCurrentHistograms(); 844 RecordCurrentHistograms();
844 845
845 log_manager_.StageCurrentLogForUpload(); 846 log_manager_.FinishCurrentLog();
846 } 847 }
847 848
848 void MetricsService::PushPendingLogsToPersistentStorage() { 849 void MetricsService::PushPendingLogsToPersistentStorage() {
849 if (state_ < INITIAL_LOG_READY) 850 if (state_ < INITIAL_LOG_READY)
850 return; // We didn't and still don't have time to get plugin list etc. 851 return; // We didn't and still don't have time to get plugin list etc.
851 852
852 if (log_manager_.has_staged_log()) { 853 if (log_manager_.has_staged_log()) {
853 if (state_ == INITIAL_LOG_READY) { 854 // We may race here, and send second copy of initial log later.
854 // We may race here, and send second copy of initial log later. 855 if (state_ == INITIAL_LOG_READY)
855 log_manager_.StoreStagedLogAsUnsent(MetricsLogManager::INITIAL_LOG);
856 state_ = SENDING_OLD_LOGS; 856 state_ = SENDING_OLD_LOGS;
857 } else { 857 log_manager_.StoreStagedLogAsUnsent();
858 // TODO(jar): Verify correctness in other states, including sending unsent
859 // initial logs.
860 log_manager_.StoreStagedLogAsUnsent(MetricsLogManager::ONGOING_LOG);
861 }
862 } 858 }
863 DCHECK(!log_manager_.has_staged_log()); 859 DCHECK(!log_manager_.has_staged_log());
864 StopRecording(); 860 StopRecording();
865 log_manager_.StoreStagedLogAsUnsent(MetricsLogManager::ONGOING_LOG);
866 StoreUnsentLogs(); 861 StoreUnsentLogs();
867 } 862 }
868 863
869 //------------------------------------------------------------------------------ 864 //------------------------------------------------------------------------------
870 // Transmission of logs methods 865 // Transmission of logs methods
871 866
872 void MetricsService::StartSchedulerIfNecessary() { 867 void MetricsService::StartSchedulerIfNecessary() {
873 if (reporting_active() && recording_active()) 868 if (reporting_active() && recording_active())
874 scheduler_->Start(); 869 scheduler_->Start();
875 } 870 }
876 871
877 void MetricsService::StartScheduledUpload() { 872 void MetricsService::StartScheduledUpload() {
878 // If reporting has been turned off, the scheduler doesn't need to run. 873 // If reporting has been turned off, the scheduler doesn't need to run.
879 if (!reporting_active() || !recording_active()) { 874 if (!reporting_active() || !recording_active()) {
880 scheduler_->Stop(); 875 scheduler_->Stop();
881 scheduler_->UploadCancelled(); 876 scheduler_->UploadCancelled();
882 return; 877 return;
883 } 878 }
884 879
880 StartFinalLogInfoCollection();
881 }
882
883 void MetricsService::StartFinalLogInfoCollection() {
884 // Begin the multi-step process of collecting memory usage histograms:
885 // First spawn a task to collect the memory details; when that task is
886 // finished, it will call OnMemoryDetailCollectionDone. That will in turn
887 // call HistogramSynchronization to collect histograms from all renderers and
888 // then call OnHistogramSynchronizationDone to continue processing.
885 DCHECK(!waiting_for_asynchronus_reporting_step_); 889 DCHECK(!waiting_for_asynchronus_reporting_step_);
886 waiting_for_asynchronus_reporting_step_ = true; 890 waiting_for_asynchronus_reporting_step_ = true;
887 891
888 base::Closure callback = 892 base::Closure callback =
889 base::Bind(&MetricsService::OnMemoryDetailCollectionDone, 893 base::Bind(&MetricsService::OnMemoryDetailCollectionDone,
890 log_sender_factory_.GetWeakPtr()); 894 log_sender_factory_.GetWeakPtr());
891 895
892 scoped_refptr<MetricsMemoryDetails> details( 896 scoped_refptr<MetricsMemoryDetails> details(
893 new MetricsMemoryDetails(callback)); 897 new MetricsMemoryDetails(callback));
894 details->StartFetch(); 898 details->StartFetch();
895 899
896 // Collect WebCore cache information to put into a histogram. 900 // Collect WebCore cache information to put into a histogram.
897 for (content::RenderProcessHost::iterator i( 901 for (content::RenderProcessHost::iterator i(
898 content::RenderProcessHost::AllHostsIterator()); 902 content::RenderProcessHost::AllHostsIterator());
899 !i.IsAtEnd(); i.Advance()) 903 !i.IsAtEnd(); i.Advance())
900 i.GetCurrentValue()->Send(new ChromeViewMsg_GetCacheResourceStats()); 904 i.GetCurrentValue()->Send(new ChromeViewMsg_GetCacheResourceStats());
901 } 905 }
902 906
903 void MetricsService::OnMemoryDetailCollectionDone() { 907 void MetricsService::OnMemoryDetailCollectionDone() {
904 DCHECK(IsSingleThreaded()); 908 DCHECK(IsSingleThreaded());
905 // This function should only be called as the callback from an ansynchronous 909 // This function should only be called as the callback from an ansynchronous
906 // step. 910 // step.
907 DCHECK(waiting_for_asynchronus_reporting_step_); 911 DCHECK(waiting_for_asynchronus_reporting_step_);
908 912
909 // Right before the UMA transmission gets started, there's one more thing we'd
910 // like to record: the histogram of memory usage, so we spawn a task to
911 // collect the memory details and when that task is finished, it will call
912 // OnMemoryDetailCollectionDone, which will call HistogramSynchronization to
913 // collect histograms from all renderers and then we will call
914 // OnHistogramSynchronizationDone to continue processing.
915
916 // Create a callback_task for OnHistogramSynchronizationDone. 913 // Create a callback_task for OnHistogramSynchronizationDone.
917 base::Closure callback = base::Bind( 914 base::Closure callback = base::Bind(
918 &MetricsService::OnHistogramSynchronizationDone, 915 &MetricsService::OnHistogramSynchronizationDone,
919 log_sender_factory_.GetWeakPtr()); 916 log_sender_factory_.GetWeakPtr());
920 917
921 base::StatisticsRecorder::CollectHistogramStats("Browser"); 918 base::StatisticsRecorder::CollectHistogramStats("Browser");
922 919
923 // Set up the callback to task to call after we receive histograms from all 920 // Set up the callback to task to call after we receive histograms from all
924 // renderer processes. Wait time specifies how long to wait before absolutely 921 // renderer processes. Wait time specifies how long to wait before absolutely
925 // calling us back on the task. 922 // calling us back on the task.
926 HistogramSynchronizer::FetchRendererHistogramsAsynchronously( 923 HistogramSynchronizer::FetchRendererHistogramsAsynchronously(
927 MessageLoop::current(), callback, 924 MessageLoop::current(), callback,
928 kMaxHistogramGatheringWaitDuration); 925 kMaxHistogramGatheringWaitDuration);
929 } 926 }
930 927
931 void MetricsService::OnHistogramSynchronizationDone() { 928 void MetricsService::OnHistogramSynchronizationDone() {
932 DCHECK(IsSingleThreaded()); 929 DCHECK(IsSingleThreaded());
930 // This function should only be called as the callback from an ansynchronous
931 // step.
932 DCHECK(waiting_for_asynchronus_reporting_step_);
933 933
934 waiting_for_asynchronus_reporting_step_ = false;
935 OnFinalLogInfoCollectionDone();
936 }
937
938 void MetricsService::OnFinalLogInfoCollectionDone() {
934 // If somehow there is a fetch in progress, we return and hope things work 939 // If somehow there is a fetch in progress, we return and hope things work
935 // out. The scheduler isn't informed since if this happens, the scheduler 940 // out. The scheduler isn't informed since if this happens, the scheduler
936 // will get a response from the upload. 941 // will get a response from the upload.
937 DCHECK(!current_fetch_.get()); 942 DCHECK(!current_fetch_.get());
938 if (current_fetch_.get()) 943 if (current_fetch_.get())
939 return; 944 return;
940 945
941 // This function should only be called as the callback from an ansynchronous
942 // step.
943 DCHECK(waiting_for_asynchronus_reporting_step_);
944 waiting_for_asynchronus_reporting_step_ = false;
945
946 // If we're getting no notifications, then the log won't have much in it, and 946 // If we're getting no notifications, then the log won't have much in it, and
947 // it's possible the computer is about to go to sleep, so don't upload and 947 // it's possible the computer is about to go to sleep, so don't upload and
948 // stop the scheduler. 948 // stop the scheduler.
949 // Similarly, if logs should no longer be uploaded, stop here. 949 // Similarly, if logs should no longer be uploaded, stop here.
950 if (idle_since_last_transmission_ || 950 if (idle_since_last_transmission_ ||
951 !recording_active() || !reporting_active()) { 951 !recording_active() || !reporting_active()) {
952 scheduler_->Stop(); 952 scheduler_->Stop();
953 scheduler_->UploadCancelled(); 953 scheduler_->UploadCancelled();
954 return; 954 return;
955 } 955 }
956 956
957 MakeStagedLog(); 957 MakeStagedLog();
958 958
959 // MakeStagedLog should have prepared log text; if it didn't, skip this 959 // MakeStagedLog should have prepared log text; if it didn't, skip this
960 // upload and hope things work out next time. 960 // upload and hope things work out next time.
961 if (log_manager_.staged_log_text().empty()) { 961 if (log_manager_.staged_log_text().empty()) {
962 scheduler_->UploadCancelled(); 962 scheduler_->UploadCancelled();
963 return; 963 return;
964 } 964 }
965 965
966 PrepareFetchWithStagedLog(); 966 SendStagedLog();
967
968 if (!current_fetch_.get()) {
969 // Compression failed, and log discarded :-/.
970 log_manager_.DiscardStagedLog();
971 scheduler_->UploadCancelled();
972 // TODO(jar): If compression failed, we should have created a tiny log and
973 // compressed that, so that we can signal that we're losing logs.
974 return;
975 }
976
977 DCHECK(!waiting_for_asynchronus_reporting_step_);
978
979 waiting_for_asynchronus_reporting_step_ = true;
980 current_fetch_->Start();
981
982 HandleIdleSinceLastTransmission(true);
983 } 967 }
984 968
985
986 void MetricsService::MakeStagedLog() { 969 void MetricsService::MakeStagedLog() {
987 if (log_manager_.has_staged_log()) 970 if (log_manager_.has_staged_log())
988 return; 971 return;
989 972
990 switch (state_) { 973 switch (state_) {
991 case INITIALIZED: 974 case INITIALIZED:
992 case INIT_TASK_SCHEDULED: // We should be further along by now. 975 case INIT_TASK_SCHEDULED: // We should be further along by now.
993 DCHECK(false); 976 DCHECK(false);
994 return; 977 return;
995 978
996 case INIT_TASK_DONE: 979 case INIT_TASK_DONE:
997 // We need to wait for the initial log to be ready before sending 980 // We need to wait for the initial log to be ready before sending
998 // anything, because the server will tell us whether it wants to hear 981 // anything, because the server will tell us whether it wants to hear
999 // from us. 982 // from us.
1000 PrepareInitialLog(); 983 PrepareInitialLog();
1001 DCHECK(state_ == INIT_TASK_DONE); 984 DCHECK(state_ == INIT_TASK_DONE);
1002 log_manager_.LoadPersistedUnsentLogs(); 985 log_manager_.LoadPersistedUnsentLogs();
1003 state_ = INITIAL_LOG_READY; 986 state_ = INITIAL_LOG_READY;
1004 break; 987 break;
1005 988
1006 case SENDING_OLD_LOGS: 989 case SENDING_OLD_LOGS:
1007 if (log_manager_.has_unsent_logs()) { 990 if (log_manager_.has_unsent_logs()) {
1008 log_manager_.StageNextStoredLogForUpload(); 991 log_manager_.StageNextLogForUpload();
1009 break; 992 break;
1010 } 993 }
1011 state_ = SENDING_CURRENT_LOGS; 994 state_ = SENDING_CURRENT_LOGS;
1012 // Fall through. 995 // Fall through.
1013 996
1014 case SENDING_CURRENT_LOGS: 997 case SENDING_CURRENT_LOGS:
1015 StopRecording(); 998 StopRecording();
1016 StartRecording(); 999 StartRecording();
1000 log_manager_.StageNextLogForUpload();
1017 break; 1001 break;
1018 1002
1019 default: 1003 default:
1020 NOTREACHED(); 1004 NOTREACHED();
1021 return; 1005 return;
1022 } 1006 }
1023 1007
1024 DCHECK(log_manager_.has_staged_log()); 1008 DCHECK(log_manager_.has_staged_log());
1025 } 1009 }
1026 1010
1027 void MetricsService::PrepareInitialLog() { 1011 void MetricsService::PrepareInitialLog() {
1028 DCHECK(state_ == INIT_TASK_DONE); 1012 DCHECK(state_ == INIT_TASK_DONE);
1029 1013
1030 MetricsLog* log = new MetricsLog(client_id_, session_id_); 1014 MetricsLog* log = new MetricsLog(client_id_, session_id_);
1031 log->set_hardware_class(hardware_class_); // Adds to initial log. 1015 log->set_hardware_class(hardware_class_); // Adds to initial log.
1032 log->RecordEnvironment(plugins_, profile_dictionary_.get()); 1016 log->RecordEnvironment(plugins_, profile_dictionary_.get());
1033 1017
1034 // Histograms only get written to the current log, so make the new log current 1018 // Histograms only get written to the current log, so make the new log current
1035 // before writing them. 1019 // before writing them.
1036 log_manager_.PauseCurrentLog(); 1020 log_manager_.PauseCurrentLog();
1037 log_manager_.BeginLoggingWithLog(log); 1021 log_manager_.BeginLoggingWithLog(log, MetricsLogManager::INITIAL_LOG);
1038 RecordCurrentHistograms(); 1022 RecordCurrentHistograms();
1023 log_manager_.FinishCurrentLog();
1024 log_manager_.ResumePausedLog();
1039 1025
1040 DCHECK(!log_manager_.has_staged_log()); 1026 DCHECK(!log_manager_.has_staged_log());
1041 log_manager_.StageCurrentLogForUpload(); 1027 log_manager_.StageNextLogForUpload();
1042 log_manager_.ResumePausedLog();
1043 } 1028 }
1044 1029
1045 void MetricsService::StoreUnsentLogs() { 1030 void MetricsService::StoreUnsentLogs() {
1046 if (state_ < INITIAL_LOG_READY) 1031 if (state_ < INITIAL_LOG_READY)
1047 return; // We never Recalled the prior unsent logs. 1032 return; // We never Recalled the prior unsent logs.
1048 1033
1049 log_manager_.PersistUnsentLogs(); 1034 log_manager_.PersistUnsentLogs();
1050 } 1035 }
1051 1036
1037 void MetricsService::SendStagedLog() {
1038 DCHECK(log_manager_.has_staged_log());
1039
1040 PrepareFetchWithStagedLog();
1041
1042 if (!current_fetch_.get()) {
1043 // Compression failed, and log discarded :-/.
1044 log_manager_.DiscardStagedLog();
1045 scheduler_->UploadCancelled();
1046 // TODO(jar): If compression failed, we should have created a tiny log and
1047 // compressed that, so that we can signal that we're losing logs.
1048 return;
1049 }
1050
1051 DCHECK(!waiting_for_asynchronus_reporting_step_);
1052
1053 waiting_for_asynchronus_reporting_step_ = true;
1054 current_fetch_->Start();
1055
1056 HandleIdleSinceLastTransmission(true);
1057 }
1058
1052 void MetricsService::PrepareFetchWithStagedLog() { 1059 void MetricsService::PrepareFetchWithStagedLog() {
1053 DCHECK(!log_manager_.staged_log_text().empty()); 1060 DCHECK(!log_manager_.staged_log_text().empty());
1054 DCHECK(!current_fetch_.get()); 1061 DCHECK(!current_fetch_.get());
1055 1062
1056 current_fetch_.reset(content::URLFetcher::Create( 1063 current_fetch_.reset(content::URLFetcher::Create(
1057 GURL(WideToUTF16(server_url_)), content::URLFetcher::POST, this)); 1064 GURL(WideToUTF16(server_url_)), content::URLFetcher::POST, this));
1058 current_fetch_->SetRequestContext( 1065 current_fetch_->SetRequestContext(
1059 g_browser_process->system_request_context()); 1066 g_browser_process->system_request_context());
1060 current_fetch_->SetUploadData(kMetricsType, log_manager_.staged_log_text()); 1067 current_fetch_->SetUploadData(kMetricsType, log_manager_.staged_log_text());
1061 } 1068 }
(...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after
1556 if (local_state) { 1563 if (local_state) {
1557 const PrefService::Preference* uma_pref = 1564 const PrefService::Preference* uma_pref =
1558 local_state->FindPreference(prefs::kMetricsReportingEnabled); 1565 local_state->FindPreference(prefs::kMetricsReportingEnabled);
1559 if (uma_pref) { 1566 if (uma_pref) {
1560 bool success = uma_pref->GetValue()->GetAsBoolean(&result); 1567 bool success = uma_pref->GetValue()->GetAsBoolean(&result);
1561 DCHECK(success); 1568 DCHECK(success);
1562 } 1569 }
1563 } 1570 }
1564 return result; 1571 return result;
1565 } 1572 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698