| 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 |