[email protected] | df32e89c | 2012-05-17 17:47:34 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | 89622004 | 2010-03-23 18:14:28 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
[email protected] | 5ccaa41 | 2009-11-13 22:00:16 | [diff] [blame] | 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "chrome/browser/chromeos/external_metrics.h" |
| 6 | |
[email protected] | f412499 | 2013-06-20 03:34:17 | [diff] [blame] | 7 | #include <map> |
[email protected] | d8e1cf9c | 2011-11-03 19:37:57 | [diff] [blame] | 8 | #include <string> |
| 9 | |
[email protected] | 7f6f44c | 2011-12-14 13:23:38 | [diff] [blame] | 10 | #include "base/bind.h" |
[email protected] | 835d7c8 | 2010-10-14 04:38:38 | [diff] [blame] | 11 | #include "base/metrics/histogram.h" |
[email protected] | 85bbf09 | 2013-05-07 08:23:40 | [diff] [blame] | 12 | #include "base/metrics/sparse_histogram.h" |
[email protected] | cbf1444 | 2012-09-05 03:00:25 | [diff] [blame] | 13 | #include "base/metrics/statistics_recorder.h" |
[email protected] | bd5a374 | 2013-09-29 18:06:13 | [diff] [blame] | 14 | #include "base/timer/elapsed_timer.h" |
[email protected] | c1834a9 | 2011-01-21 18:21:03 | [diff] [blame] | 15 | #include "chrome/browser/browser_process.h" |
[email protected] | 8304f61a | 2014-05-24 12:17:33 | [diff] [blame] | 16 | #include "chrome/browser/metrics/chromeos_metrics_provider.h" |
[email protected] | d6147bd | 2014-06-11 01:58:19 | [diff] [blame] | 17 | #include "components/metrics/metrics_service.h" |
[email protected] | 1ebdce33 | 2014-07-17 21:19:19 | [diff] [blame] | 18 | #include "components/metrics/serialization/metric_sample.h" |
| 19 | #include "components/metrics/serialization/serialization_utils.h" |
[email protected] | c38831a1 | 2011-10-28 12:44:49 | [diff] [blame] | 20 | #include "content/public/browser/browser_thread.h" |
[email protected] | 7f6f44c | 2011-12-14 13:23:38 | [diff] [blame] | 21 | #include "content/public/browser/user_metrics.h" |
[email protected] | 5ccaa41 | 2009-11-13 22:00:16 | [diff] [blame] | 22 | |
[email protected] | e6e30ac | 2014-01-13 21:24:39 | [diff] [blame] | 23 | using base::UserMetricsAction; |
[email protected] | 631bb74 | 2011-11-02 11:29:39 | [diff] [blame] | 24 | using content::BrowserThread; |
[email protected] | 631bb74 | 2011-11-02 11:29:39 | [diff] [blame] | 25 | |
[email protected] | 5ccaa41 | 2009-11-13 22:00:16 | [diff] [blame] | 26 | namespace chromeos { |
| 27 | |
[email protected] | abae9b02 | 2012-10-24 08:18:52 | [diff] [blame] | 28 | namespace { |
| 29 | |
| 30 | bool CheckValues(const std::string& name, |
| 31 | int minimum, |
| 32 | int maximum, |
| 33 | size_t bucket_count) { |
| 34 | if (!base::Histogram::InspectConstructionArguments( |
| 35 | name, &minimum, &maximum, &bucket_count)) |
| 36 | return false; |
| 37 | base::HistogramBase* histogram = |
| 38 | base::StatisticsRecorder::FindHistogram(name); |
| 39 | if (!histogram) |
| 40 | return true; |
| 41 | return histogram->HasConstructionArguments(minimum, maximum, bucket_count); |
| 42 | } |
| 43 | |
| 44 | bool CheckLinearValues(const std::string& name, int maximum) { |
| 45 | return CheckValues(name, 1, maximum, maximum + 1); |
| 46 | } |
| 47 | |
| 48 | } // namespace |
| 49 | |
[email protected] | df32e89c | 2012-05-17 17:47:34 | [diff] [blame] | 50 | // The interval between external metrics collections in seconds |
| 51 | static const int kExternalMetricsCollectionIntervalSeconds = 30; |
semenzato | ba56da0 | 2015-03-12 21:05:19 | [diff] [blame] | 52 | const char kEventsFilePath[] = "/var/lib/metrics/uma-events"; |
[email protected] | 5ccaa41 | 2009-11-13 22:00:16 | [diff] [blame] | 53 | |
[email protected] | d5985de | 2014-05-28 15:24:48 | [diff] [blame] | 54 | ExternalMetrics::ExternalMetrics() : uma_events_file_(kEventsFilePath) { |
| 55 | } |
[email protected] | 5ccaa41 | 2009-11-13 22:00:16 | [diff] [blame] | 56 | |
[email protected] | 41baad0 | 2011-05-15 20:37:46 | [diff] [blame] | 57 | ExternalMetrics::~ExternalMetrics() {} |
| 58 | |
[email protected] | 29cf1677 | 2010-04-21 15:13:47 | [diff] [blame] | 59 | void ExternalMetrics::Start() { |
isherman | de9efab | 2015-03-31 00:01:25 | [diff] [blame^] | 60 | ScheduleCollector(); |
[email protected] | 5ccaa41 | 2009-11-13 22:00:16 | [diff] [blame] | 61 | } |
| 62 | |
[email protected] | d5985de | 2014-05-28 15:24:48 | [diff] [blame] | 63 | // static |
| 64 | scoped_refptr<ExternalMetrics> ExternalMetrics::CreateForTesting( |
| 65 | const std::string& filename) { |
| 66 | scoped_refptr<ExternalMetrics> external_metrics(new ExternalMetrics()); |
| 67 | external_metrics->uma_events_file_ = filename; |
| 68 | return external_metrics; |
| 69 | } |
| 70 | |
isherman | de9efab | 2015-03-31 00:01:25 | [diff] [blame^] | 71 | void ExternalMetrics::RecordActionUI(const std::string& action_string) { |
| 72 | content::RecordComputedAction(action_string); |
[email protected] | 5ccaa41 | 2009-11-13 22:00:16 | [diff] [blame] | 73 | } |
| 74 | |
[email protected] | d5985de | 2014-05-28 15:24:48 | [diff] [blame] | 75 | void ExternalMetrics::RecordAction(const std::string& action) { |
[email protected] | cca169b5 | 2010-10-08 22:15:55 | [diff] [blame] | 76 | BrowserThread::PostTask( |
[email protected] | d5985de | 2014-05-28 15:24:48 | [diff] [blame] | 77 | BrowserThread::UI, |
| 78 | FROM_HERE, |
| 79 | base::Bind(&ExternalMetrics::RecordActionUI, this, action)); |
[email protected] | 29cf1677 | 2010-04-21 15:13:47 | [diff] [blame] | 80 | } |
| 81 | |
[email protected] | c1834a9 | 2011-01-21 18:21:03 | [diff] [blame] | 82 | void ExternalMetrics::RecordCrashUI(const std::string& crash_kind) { |
[email protected] | 8304f61a | 2014-05-24 12:17:33 | [diff] [blame] | 83 | ChromeOSMetricsProvider::LogCrash(crash_kind); |
[email protected] | c1834a9 | 2011-01-21 18:21:03 | [diff] [blame] | 84 | } |
| 85 | |
| 86 | void ExternalMetrics::RecordCrash(const std::string& crash_kind) { |
| 87 | BrowserThread::PostTask( |
| 88 | BrowserThread::UI, FROM_HERE, |
[email protected] | d8e1cf9c | 2011-11-03 19:37:57 | [diff] [blame] | 89 | base::Bind(&ExternalMetrics::RecordCrashUI, this, crash_kind)); |
[email protected] | c1834a9 | 2011-01-21 18:21:03 | [diff] [blame] | 90 | } |
| 91 | |
[email protected] | d5985de | 2014-05-28 15:24:48 | [diff] [blame] | 92 | void ExternalMetrics::RecordHistogram(const metrics::MetricSample& sample) { |
| 93 | CHECK_EQ(metrics::MetricSample::HISTOGRAM, sample.type()); |
| 94 | if (!CheckValues( |
| 95 | sample.name(), sample.min(), sample.max(), sample.bucket_count())) { |
| 96 | DLOG(ERROR) << "Invalid histogram: " << sample.name(); |
[email protected] | 29cf1677 | 2010-04-21 15:13:47 | [diff] [blame] | 97 | return; |
| 98 | } |
[email protected] | e24a853 | 2012-08-03 07:18:44 | [diff] [blame] | 99 | |
[email protected] | d5985de | 2014-05-28 15:24:48 | [diff] [blame] | 100 | base::HistogramBase* counter = |
| 101 | base::Histogram::FactoryGet(sample.name(), |
| 102 | sample.min(), |
| 103 | sample.max(), |
| 104 | sample.bucket_count(), |
| 105 | base::Histogram::kUmaTargetedHistogramFlag); |
| 106 | counter->Add(sample.sample()); |
[email protected] | 29cf1677 | 2010-04-21 15:13:47 | [diff] [blame] | 107 | } |
| 108 | |
[email protected] | d5985de | 2014-05-28 15:24:48 | [diff] [blame] | 109 | void ExternalMetrics::RecordLinearHistogram( |
| 110 | const metrics::MetricSample& sample) { |
| 111 | CHECK_EQ(metrics::MetricSample::LINEAR_HISTOGRAM, sample.type()); |
| 112 | if (!CheckLinearValues(sample.name(), sample.max())) { |
| 113 | DLOG(ERROR) << "Invalid linear histogram: " << sample.name(); |
[email protected] | 29cf1677 | 2010-04-21 15:13:47 | [diff] [blame] | 114 | return; |
| 115 | } |
[email protected] | de41555 | 2013-01-23 04:12:17 | [diff] [blame] | 116 | base::HistogramBase* counter = base::LinearHistogram::FactoryGet( |
[email protected] | d5985de | 2014-05-28 15:24:48 | [diff] [blame] | 117 | sample.name(), |
| 118 | 1, |
| 119 | sample.max(), |
| 120 | sample.max() + 1, |
| 121 | base::Histogram::kUmaTargetedHistogramFlag); |
| 122 | counter->Add(sample.sample()); |
[email protected] | 29cf1677 | 2010-04-21 15:13:47 | [diff] [blame] | 123 | } |
| 124 | |
[email protected] | d5985de | 2014-05-28 15:24:48 | [diff] [blame] | 125 | void ExternalMetrics::RecordSparseHistogram( |
| 126 | const metrics::MetricSample& sample) { |
| 127 | CHECK_EQ(metrics::MetricSample::SPARSE_HISTOGRAM, sample.type()); |
[email protected] | 85bbf09 | 2013-05-07 08:23:40 | [diff] [blame] | 128 | base::HistogramBase* counter = base::SparseHistogram::FactoryGet( |
[email protected] | d5985de | 2014-05-28 15:24:48 | [diff] [blame] | 129 | sample.name(), base::HistogramBase::kUmaTargetedHistogramFlag); |
| 130 | counter->Add(sample.sample()); |
[email protected] | 85bbf09 | 2013-05-07 08:23:40 | [diff] [blame] | 131 | } |
| 132 | |
[email protected] | d5985de | 2014-05-28 15:24:48 | [diff] [blame] | 133 | int ExternalMetrics::CollectEvents() { |
| 134 | ScopedVector<metrics::MetricSample> samples; |
| 135 | metrics::SerializationUtils::ReadAndTruncateMetricsFromFile(uma_events_file_, |
| 136 | &samples); |
| 137 | |
| 138 | for (ScopedVector<metrics::MetricSample>::iterator it = samples.begin(); |
| 139 | it != samples.end(); |
| 140 | ++it) { |
| 141 | const metrics::MetricSample& sample = **it; |
| 142 | |
| 143 | // Do not use the UMA_HISTOGRAM_... macros here. They cache the Histogram |
| 144 | // instance and thus only work if |sample.name()| is constant. |
| 145 | switch (sample.type()) { |
| 146 | case metrics::MetricSample::CRASH: |
| 147 | RecordCrash(sample.name()); |
| 148 | break; |
| 149 | case metrics::MetricSample::USER_ACTION: |
| 150 | RecordAction(sample.name()); |
| 151 | break; |
| 152 | case metrics::MetricSample::HISTOGRAM: |
| 153 | RecordHistogram(sample); |
| 154 | break; |
| 155 | case metrics::MetricSample::LINEAR_HISTOGRAM: |
| 156 | RecordLinearHistogram(sample); |
| 157 | break; |
| 158 | case metrics::MetricSample::SPARSE_HISTOGRAM: |
| 159 | RecordSparseHistogram(sample); |
| 160 | break; |
[email protected] | 5ccaa41 | 2009-11-13 22:00:16 | [diff] [blame] | 161 | } |
| 162 | } |
| 163 | |
[email protected] | d5985de | 2014-05-28 15:24:48 | [diff] [blame] | 164 | return samples.size(); |
[email protected] | 5ccaa41 | 2009-11-13 22:00:16 | [diff] [blame] | 165 | } |
| 166 | |
| 167 | void ExternalMetrics::CollectEventsAndReschedule() { |
[email protected] | bd5a374 | 2013-09-29 18:06:13 | [diff] [blame] | 168 | base::ElapsedTimer timer; |
[email protected] | 5ccaa41 | 2009-11-13 22:00:16 | [diff] [blame] | 169 | CollectEvents(); |
[email protected] | d2b6af67 | 2010-07-01 20:38:54 | [diff] [blame] | 170 | UMA_HISTOGRAM_TIMES("UMA.CollectExternalEventsTime", timer.Elapsed()); |
[email protected] | 5ccaa41 | 2009-11-13 22:00:16 | [diff] [blame] | 171 | ScheduleCollector(); |
| 172 | } |
| 173 | |
| 174 | void ExternalMetrics::ScheduleCollector() { |
isherman | de9efab | 2015-03-31 00:01:25 | [diff] [blame^] | 175 | bool result = BrowserThread::PostDelayedTask( |
[email protected] | 85bbf09 | 2013-05-07 08:23:40 | [diff] [blame] | 176 | BrowserThread::FILE, FROM_HERE, |
| 177 | base::Bind(&chromeos::ExternalMetrics::CollectEventsAndReschedule, this), |
| 178 | base::TimeDelta::FromSeconds(kExternalMetricsCollectionIntervalSeconds)); |
[email protected] | 5ccaa41 | 2009-11-13 22:00:16 | [diff] [blame] | 179 | DCHECK(result); |
| 180 | } |
| 181 | |
[email protected] | 5ccaa41 | 2009-11-13 22:00:16 | [diff] [blame] | 182 | } // namespace chromeos |