OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 | 6 |
7 //------------------------------------------------------------------------------ | 7 //------------------------------------------------------------------------------ |
8 // Description of the life cycle of a instance of MetricsService. | 8 // Description of the life cycle of a instance of MetricsService. |
9 // | 9 // |
10 // OVERVIEW | 10 // OVERVIEW |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 prefs::kMetricsOngoingLogs); | 401 prefs::kMetricsOngoingLogs); |
402 unsent_ongoing_logs->Clear(); | 402 unsent_ongoing_logs->Clear(); |
403 } | 403 } |
404 | 404 |
405 MetricsService::MetricsService() | 405 MetricsService::MetricsService() |
406 : recording_active_(false), | 406 : recording_active_(false), |
407 reporting_active_(false), | 407 reporting_active_(false), |
408 user_permits_upload_(false), | 408 user_permits_upload_(false), |
409 server_permits_upload_(true), | 409 server_permits_upload_(true), |
410 state_(INITIALIZED), | 410 state_(INITIALIZED), |
411 pending_log_(NULL), | |
412 pending_log_text_(), | |
413 current_fetch_(NULL), | 411 current_fetch_(NULL), |
414 current_log_(NULL), | |
415 idle_since_last_transmission_(false), | 412 idle_since_last_transmission_(false), |
416 next_window_id_(0), | 413 next_window_id_(0), |
417 ALLOW_THIS_IN_INITIALIZER_LIST(log_sender_factory_(this)), | 414 ALLOW_THIS_IN_INITIALIZER_LIST(log_sender_factory_(this)), |
418 ALLOW_THIS_IN_INITIALIZER_LIST(state_saver_factory_(this)), | 415 ALLOW_THIS_IN_INITIALIZER_LIST(state_saver_factory_(this)), |
419 logged_samples_(), | |
420 interlog_duration_(TimeDelta::FromSeconds(kInitialInterlogDuration)), | 416 interlog_duration_(TimeDelta::FromSeconds(kInitialInterlogDuration)), |
421 log_event_limit_(kInitialEventLimit), | 417 log_event_limit_(kInitialEventLimit), |
422 timer_pending_(false) { | 418 timer_pending_(false) { |
423 DCHECK(IsSingleThreaded()); | 419 DCHECK(IsSingleThreaded()); |
424 InitializeMetricsState(); | 420 InitializeMetricsState(); |
425 } | 421 } |
426 | 422 |
427 MetricsService::~MetricsService() { | 423 MetricsService::~MetricsService() { |
428 SetRecording(false); | 424 SetRecording(false); |
429 if (pending_log_) { | |
430 delete pending_log_; | |
431 pending_log_ = NULL; | |
432 } | |
433 if (current_log_) { | |
434 delete current_log_; | |
435 current_log_ = NULL; | |
436 } | |
437 } | 425 } |
438 | 426 |
439 void MetricsService::SetUserPermitsUpload(bool enabled) { | 427 void MetricsService::SetUserPermitsUpload(bool enabled) { |
440 HandleIdleSinceLastTransmission(false); | 428 HandleIdleSinceLastTransmission(false); |
441 user_permits_upload_ = enabled; | 429 user_permits_upload_ = enabled; |
442 } | 430 } |
443 | 431 |
444 void MetricsService::Start() { | 432 void MetricsService::Start() { |
445 SetRecording(true); | 433 SetRecording(true); |
446 SetReporting(true); | 434 SetReporting(true); |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
590 case NotificationType::CHILD_PROCESS_HOST_CONNECTED: | 578 case NotificationType::CHILD_PROCESS_HOST_CONNECTED: |
591 case NotificationType::CHILD_PROCESS_CRASHED: | 579 case NotificationType::CHILD_PROCESS_CRASHED: |
592 case NotificationType::CHILD_INSTANCE_CREATED: | 580 case NotificationType::CHILD_INSTANCE_CREATED: |
593 LogChildProcessChange(type, source, details); | 581 LogChildProcessChange(type, source, details); |
594 break; | 582 break; |
595 | 583 |
596 case NotificationType::TEMPLATE_URL_MODEL_LOADED: | 584 case NotificationType::TEMPLATE_URL_MODEL_LOADED: |
597 LogKeywords(Source<TemplateURLModel>(source).ptr()); | 585 LogKeywords(Source<TemplateURLModel>(source).ptr()); |
598 break; | 586 break; |
599 | 587 |
600 case NotificationType::OMNIBOX_OPENED_URL: | 588 case NotificationType::OMNIBOX_OPENED_URL: { |
601 current_log_->RecordOmniboxOpenedURL( | 589 MetricsLog* current_log = current_log_->AsMetricsLog(); |
| 590 DCHECK(current_log); |
| 591 current_log->RecordOmniboxOpenedURL( |
602 *Details<AutocompleteLog>(details).ptr()); | 592 *Details<AutocompleteLog>(details).ptr()); |
603 break; | 593 break; |
| 594 } |
604 | 595 |
605 case NotificationType::BOOKMARK_MODEL_LOADED: { | 596 case NotificationType::BOOKMARK_MODEL_LOADED: { |
606 Profile* p = Source<Profile>(source).ptr(); | 597 Profile* p = Source<Profile>(source).ptr(); |
607 if (p) | 598 if (p) |
608 LogBookmarks(p->GetBookmarkModel()); | 599 LogBookmarks(p->GetBookmarkModel()); |
609 break; | 600 break; |
610 } | 601 } |
611 default: | 602 default: |
612 LOG(DFATAL); | 603 LOG(DFATAL); |
613 break; | 604 break; |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
841 // Schedules a task on the file thread for execution of slower | 832 // Schedules a task on the file thread for execution of slower |
842 // initialization steps (such as plugin list generation) necessary | 833 // initialization steps (such as plugin list generation) necessary |
843 // for sending the initial log. This avoids blocking the main UI | 834 // for sending the initial log. This avoids blocking the main UI |
844 // thread. | 835 // thread. |
845 g_browser_process->file_thread()->message_loop()->PostDelayedTask(FROM_HERE, | 836 g_browser_process->file_thread()->message_loop()->PostDelayedTask(FROM_HERE, |
846 new InitTask(MessageLoop::current()), | 837 new InitTask(MessageLoop::current()), |
847 kInitialInterlogDuration * 1000 / 2); | 838 kInitialInterlogDuration * 1000 / 2); |
848 } | 839 } |
849 } | 840 } |
850 | 841 |
851 void MetricsService::StopRecording(MetricsLog** log) { | 842 void MetricsService::StopRecording(MetricsLogBase** log) { |
852 if (!current_log_) | 843 if (!current_log_) |
853 return; | 844 return; |
854 | 845 |
855 current_log_->set_hardware_class(hardware_class_); // Adds to ongoing logs. | 846 MetricsLog* current_log = current_log_->AsMetricsLog(); |
| 847 DCHECK(current_log); |
| 848 current_log->set_hardware_class(hardware_class_); // Adds to ongoing logs. |
856 | 849 |
857 // TODO(jar): Integrate bounds on log recording more consistently, so that we | 850 // TODO(jar): Integrate bounds on log recording more consistently, so that we |
858 // can stop recording logs that are too big much sooner. | 851 // can stop recording logs that are too big much sooner. |
859 if (current_log_->num_events() > log_event_limit_) { | 852 if (current_log_->num_events() > log_event_limit_) { |
860 UMA_HISTOGRAM_COUNTS("UMA.Discarded Log Events", | 853 UMA_HISTOGRAM_COUNTS("UMA.Discarded Log Events", |
861 current_log_->num_events()); | 854 current_log_->num_events()); |
862 current_log_->CloseLog(); | 855 current_log_->CloseLog(); |
863 delete current_log_; | 856 delete current_log_; |
864 current_log_ = NULL; | 857 current_log_ = NULL; |
865 StartRecording(); // Start trivial log to hold our histograms. | 858 StartRecording(); // Start trivial log to hold our histograms. |
866 } | 859 } |
867 | 860 |
868 // Put incremental data (histogram deltas, and realtime stats deltas) at the | 861 // Put incremental data (histogram deltas, and realtime stats deltas) at the |
869 // end of all log transmissions (initial log handles this separately). | 862 // end of all log transmissions (initial log handles this separately). |
870 // Don't bother if we're going to discard current_log_. | 863 // Don't bother if we're going to discard current_log_. |
871 if (log) { | 864 if (log) { |
872 current_log_->RecordIncrementalStabilityElements(); | 865 current_log->RecordIncrementalStabilityElements(); |
873 RecordCurrentHistograms(); | 866 RecordCurrentHistograms(); |
874 } | 867 } |
875 | 868 |
876 current_log_->CloseLog(); | 869 current_log_->CloseLog(); |
877 if (log) | 870 if (log) |
878 *log = current_log_; | 871 *log = current_log; |
879 else | 872 else |
880 delete current_log_; | 873 delete current_log_; |
881 current_log_ = NULL; | 874 current_log_ = NULL; |
882 } | 875 } |
883 | 876 |
884 void MetricsService::PushPendingLogsToUnsentLists() { | 877 void MetricsService::PushPendingLogsToUnsentLists() { |
885 if (state_ < INITIAL_LOG_READY) | 878 if (state_ < INITIAL_LOG_READY) |
886 return; // We didn't and still don't have time to get plugin list etc. | 879 return; // We didn't and still don't have time to get plugin list etc. |
887 | 880 |
888 if (pending_log()) { | 881 if (pending_log()) { |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1134 } | 1127 } |
1135 | 1128 |
1136 void MetricsService::PrepareInitialLog() { | 1129 void MetricsService::PrepareInitialLog() { |
1137 DCHECK(state_ == INIT_TASK_DONE); | 1130 DCHECK(state_ == INIT_TASK_DONE); |
1138 | 1131 |
1139 MetricsLog* log = new MetricsLog(client_id_, session_id_); | 1132 MetricsLog* log = new MetricsLog(client_id_, session_id_); |
1140 log->set_hardware_class(hardware_class_); // Adds to initial log. | 1133 log->set_hardware_class(hardware_class_); // Adds to initial log. |
1141 log->RecordEnvironment(plugins_, profile_dictionary_.get()); | 1134 log->RecordEnvironment(plugins_, profile_dictionary_.get()); |
1142 | 1135 |
1143 // Histograms only get written to current_log_, so setup for the write. | 1136 // Histograms only get written to current_log_, so setup for the write. |
1144 MetricsLog* save_log = current_log_; | 1137 MetricsLogBase* save_log = current_log_; |
1145 current_log_ = log; | 1138 current_log_ = log; |
1146 RecordCurrentHistograms(); // Into current_log_... which is really log. | 1139 RecordCurrentHistograms(); // Into current_log_... which is really log. |
1147 current_log_ = save_log; | 1140 current_log_ = save_log; |
1148 | 1141 |
1149 log->CloseLog(); | 1142 log->CloseLog(); |
1150 DCHECK(!pending_log()); | 1143 DCHECK(!pending_log()); |
1151 pending_log_ = log; | 1144 pending_log_ = log; |
1152 } | 1145 } |
1153 | 1146 |
1154 void MetricsService::RecallUnsentLogs() { | 1147 void MetricsService::RecallUnsentLogs() { |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1233 return; | 1226 return; |
1234 } | 1227 } |
1235 | 1228 |
1236 current_fetch_.reset(new URLFetcher(GURL(WideToUTF16(server_url_)), | 1229 current_fetch_.reset(new URLFetcher(GURL(WideToUTF16(server_url_)), |
1237 URLFetcher::POST, | 1230 URLFetcher::POST, |
1238 this)); | 1231 this)); |
1239 current_fetch_->set_request_context(Profile::GetDefaultRequestContext()); | 1232 current_fetch_->set_request_context(Profile::GetDefaultRequestContext()); |
1240 current_fetch_->set_upload_data(kMetricsType, compressed_log); | 1233 current_fetch_->set_upload_data(kMetricsType, compressed_log); |
1241 } | 1234 } |
1242 | 1235 |
1243 void MetricsService::DiscardPendingLog() { | |
1244 if (pending_log_) { // Shutdown might have deleted it! | |
1245 delete pending_log_; | |
1246 pending_log_ = NULL; | |
1247 } | |
1248 pending_log_text_.clear(); | |
1249 } | |
1250 | |
1251 // This implementation is based on the Firefox MetricsService implementation. | |
1252 bool MetricsService::Bzip2Compress(const std::string& input, | |
1253 std::string* output) { | |
1254 bz_stream stream = {0}; | |
1255 // As long as our input is smaller than the bzip2 block size, we should get | |
1256 // the best compression. For example, if your input was 250k, using a block | |
1257 // size of 300k or 500k should result in the same compression ratio. Since | |
1258 // our data should be under 100k, using the minimum block size of 100k should | |
1259 // allocate less temporary memory, but result in the same compression ratio. | |
1260 int result = BZ2_bzCompressInit(&stream, | |
1261 1, // 100k (min) block size | |
1262 0, // quiet | |
1263 0); // default "work factor" | |
1264 if (result != BZ_OK) { // out of memory? | |
1265 return false; | |
1266 } | |
1267 | |
1268 output->clear(); | |
1269 | |
1270 stream.next_in = const_cast<char*>(input.data()); | |
1271 stream.avail_in = static_cast<int>(input.size()); | |
1272 // NOTE: we don't need a BZ_RUN phase since our input buffer contains | |
1273 // the entire input | |
1274 do { | |
1275 output->resize(output->size() + 1024); | |
1276 stream.next_out = &((*output)[stream.total_out_lo32]); | |
1277 stream.avail_out = static_cast<int>(output->size()) - stream.total_out_lo32; | |
1278 result = BZ2_bzCompress(&stream, BZ_FINISH); | |
1279 } while (result == BZ_FINISH_OK); | |
1280 if (result != BZ_STREAM_END) // unknown failure? | |
1281 return false; | |
1282 result = BZ2_bzCompressEnd(&stream); | |
1283 DCHECK(result == BZ_OK); | |
1284 | |
1285 output->resize(stream.total_out_lo32); | |
1286 | |
1287 return true; | |
1288 } | |
1289 | |
1290 static const char* StatusToString(const URLRequestStatus& status) { | 1236 static const char* StatusToString(const URLRequestStatus& status) { |
1291 switch (status.status()) { | 1237 switch (status.status()) { |
1292 case URLRequestStatus::SUCCESS: | 1238 case URLRequestStatus::SUCCESS: |
1293 return "SUCCESS"; | 1239 return "SUCCESS"; |
1294 | 1240 |
1295 case URLRequestStatus::IO_PENDING: | 1241 case URLRequestStatus::IO_PENDING: |
1296 return "IO_PENDING"; | 1242 return "IO_PENDING"; |
1297 | 1243 |
1298 case URLRequestStatus::HANDLED_EXTERNALLY: | 1244 case URLRequestStatus::HANDLED_EXTERNALLY: |
1299 return "HANDLED_EXTERNALLY"; | 1245 return "HANDLED_EXTERNALLY"; |
(...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1869 pref->SetBoolean(path, value); | 1815 pref->SetBoolean(path, value); |
1870 RecordCurrentState(pref); | 1816 RecordCurrentState(pref); |
1871 } | 1817 } |
1872 | 1818 |
1873 void MetricsService::RecordCurrentState(PrefService* pref) { | 1819 void MetricsService::RecordCurrentState(PrefService* pref) { |
1874 pref->SetInt64(prefs::kStabilityLastTimestampSec, Time::Now().ToTimeT()); | 1820 pref->SetInt64(prefs::kStabilityLastTimestampSec, Time::Now().ToTimeT()); |
1875 | 1821 |
1876 RecordPluginChanges(pref); | 1822 RecordPluginChanges(pref); |
1877 } | 1823 } |
1878 | 1824 |
1879 void MetricsService::RecordCurrentHistograms() { | |
1880 DCHECK(current_log_); | |
1881 | |
1882 StatisticsRecorder::Histograms histograms; | |
1883 StatisticsRecorder::GetHistograms(&histograms); | |
1884 for (StatisticsRecorder::Histograms::iterator it = histograms.begin(); | |
1885 histograms.end() != it; | |
1886 ++it) { | |
1887 if ((*it)->flags() & Histogram::kUmaTargetedHistogramFlag) | |
1888 // TODO(petersont): Only record historgrams if they are not precluded by | |
1889 // the UMA response data. | |
1890 // Bug http://code.google.com/p/chromium/issues/detail?id=2739. | |
1891 RecordHistogram(**it); | |
1892 } | |
1893 } | |
1894 | |
1895 void MetricsService::RecordHistogram(const Histogram& histogram) { | |
1896 // Get up-to-date snapshot of sample stats. | |
1897 Histogram::SampleSet snapshot; | |
1898 histogram.SnapshotSample(&snapshot); | |
1899 | |
1900 const std::string& histogram_name = histogram.histogram_name(); | |
1901 | |
1902 // Find the already sent stats, or create an empty set. | |
1903 LoggedSampleMap::iterator it = logged_samples_.find(histogram_name); | |
1904 Histogram::SampleSet* already_logged; | |
1905 if (logged_samples_.end() == it) { | |
1906 // Add new entry | |
1907 already_logged = &logged_samples_[histogram.histogram_name()]; | |
1908 already_logged->Resize(histogram); // Complete initialization. | |
1909 } else { | |
1910 already_logged = &(it->second); | |
1911 // Deduct any stats we've already logged from our snapshot. | |
1912 snapshot.Subtract(*already_logged); | |
1913 } | |
1914 | |
1915 // snapshot now contains only a delta to what we've already_logged. | |
1916 | |
1917 if (snapshot.TotalCount() > 0) { | |
1918 current_log_->RecordHistogramDelta(histogram, snapshot); | |
1919 // Add new data into our running total. | |
1920 already_logged->Add(snapshot); | |
1921 } | |
1922 } | |
1923 | |
1924 static bool IsSingleThreaded() { | 1825 static bool IsSingleThreaded() { |
1925 static PlatformThreadId thread_id = 0; | 1826 static PlatformThreadId thread_id = 0; |
1926 if (!thread_id) | 1827 if (!thread_id) |
1927 thread_id = PlatformThread::CurrentId(); | 1828 thread_id = PlatformThread::CurrentId(); |
1928 return PlatformThread::CurrentId() == thread_id; | 1829 return PlatformThread::CurrentId() == thread_id; |
1929 } | 1830 } |
1930 | 1831 |
1931 #if defined(OS_CHROMEOS) | 1832 #if defined(OS_CHROMEOS) |
1932 // static | 1833 // static |
1933 std::string MetricsService::GetHardwareClass() { | 1834 std::string MetricsService::GetHardwareClass() { |
1934 DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::UI)); | 1835 DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::UI)); |
1935 std::string hardware_class; | 1836 std::string hardware_class; |
1936 FilePath tool(kHardwareClassTool); | 1837 FilePath tool(kHardwareClassTool); |
1937 CommandLine command(tool); | 1838 CommandLine command(tool); |
1938 if (base::GetAppOutput(command, &hardware_class)) { | 1839 if (base::GetAppOutput(command, &hardware_class)) { |
1939 TrimWhitespaceASCII(hardware_class, TRIM_ALL, &hardware_class); | 1840 TrimWhitespaceASCII(hardware_class, TRIM_ALL, &hardware_class); |
1940 } else { | 1841 } else { |
1941 hardware_class = kUnknownHardwareClass; | 1842 hardware_class = kUnknownHardwareClass; |
1942 } | 1843 } |
1943 return hardware_class; | 1844 return hardware_class; |
1944 } | 1845 } |
1945 | 1846 |
1946 void MetricsService::StartExternalMetrics() { | 1847 void MetricsService::StartExternalMetrics() { |
1947 external_metrics_ = new chromeos::ExternalMetrics; | 1848 external_metrics_ = new chromeos::ExternalMetrics; |
1948 external_metrics_->Start(); | 1849 external_metrics_->Start(); |
1949 } | 1850 } |
1950 #endif | 1851 #endif |
OLD | NEW |