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
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/external_metrics.h"
10 #include "base/bind.h"
11 #include "base/metrics/histogram.h"
12 #include "base/metrics/sparse_histogram.h"
13 #include "base/metrics/statistics_recorder.h"
14 #include "base/timer/elapsed_timer.h"
15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/metrics/chromeos_metrics_provider.h"
17 #include "components/metrics/metrics_service.h"
18 #include "components/metrics/serialization/metric_sample.h"
19 #include "components/metrics/serialization/serialization_utils.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "content/public/browser/user_metrics.h"
23 using base::UserMetricsAction
;
24 using content::BrowserThread
;
30 bool CheckValues(const std::string
& name
,
33 size_t bucket_count
) {
34 if (!base::Histogram::InspectConstructionArguments(
35 name
, &minimum
, &maximum
, &bucket_count
))
37 base::HistogramBase
* histogram
=
38 base::StatisticsRecorder::FindHistogram(name
);
41 return histogram
->HasConstructionArguments(minimum
, maximum
, bucket_count
);
44 bool CheckLinearValues(const std::string
& name
, int maximum
) {
45 return CheckValues(name
, 1, maximum
, maximum
+ 1);
50 // The interval between external metrics collections in seconds
51 static const int kExternalMetricsCollectionIntervalSeconds
= 30;
52 const char kEventsFilePath
[] = "/var/lib/metrics/uma-events";
54 ExternalMetrics::ExternalMetrics() : uma_events_file_(kEventsFilePath
) {
57 ExternalMetrics::~ExternalMetrics() {}
59 void ExternalMetrics::Start() {
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
;
71 void ExternalMetrics::RecordActionUI(const std::string
& action_string
) {
72 content::RecordComputedAction(action_string
);
75 void ExternalMetrics::RecordAction(const std::string
& action
) {
76 BrowserThread::PostTask(
79 base::Bind(&ExternalMetrics::RecordActionUI
, this, action
));
82 void ExternalMetrics::RecordCrashUI(const std::string
& crash_kind
) {
83 ChromeOSMetricsProvider::LogCrash(crash_kind
);
86 void ExternalMetrics::RecordCrash(const std::string
& crash_kind
) {
87 BrowserThread::PostTask(
88 BrowserThread::UI
, FROM_HERE
,
89 base::Bind(&ExternalMetrics::RecordCrashUI
, this, crash_kind
));
92 void ExternalMetrics::RecordHistogram(const metrics::MetricSample
& sample
) {
93 CHECK_EQ(metrics::MetricSample::HISTOGRAM
, sample
.type());
95 sample
.name(), sample
.min(), sample
.max(), sample
.bucket_count())) {
96 DLOG(ERROR
) << "Invalid histogram: " << sample
.name();
100 base::HistogramBase
* counter
=
101 base::Histogram::FactoryGet(sample
.name(),
104 sample
.bucket_count(),
105 base::Histogram::kUmaTargetedHistogramFlag
);
106 counter
->Add(sample
.sample());
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();
116 base::HistogramBase
* counter
= base::LinearHistogram::FactoryGet(
121 base::Histogram::kUmaTargetedHistogramFlag
);
122 counter
->Add(sample
.sample());
125 void ExternalMetrics::RecordSparseHistogram(
126 const metrics::MetricSample
& sample
) {
127 CHECK_EQ(metrics::MetricSample::SPARSE_HISTOGRAM
, sample
.type());
128 base::HistogramBase
* counter
= base::SparseHistogram::FactoryGet(
129 sample
.name(), base::HistogramBase::kUmaTargetedHistogramFlag
);
130 counter
->Add(sample
.sample());
133 int ExternalMetrics::CollectEvents() {
134 ScopedVector
<metrics::MetricSample
> samples
;
135 metrics::SerializationUtils::ReadAndTruncateMetricsFromFile(uma_events_file_
,
138 for (ScopedVector
<metrics::MetricSample
>::iterator it
= samples
.begin();
141 const metrics::MetricSample
& sample
= **it
;
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());
149 case metrics::MetricSample::USER_ACTION
:
150 RecordAction(sample
.name());
152 case metrics::MetricSample::HISTOGRAM
:
153 RecordHistogram(sample
);
155 case metrics::MetricSample::LINEAR_HISTOGRAM
:
156 RecordLinearHistogram(sample
);
158 case metrics::MetricSample::SPARSE_HISTOGRAM
:
159 RecordSparseHistogram(sample
);
164 return samples
.size();
167 void ExternalMetrics::CollectEventsAndReschedule() {
168 base::ElapsedTimer timer
;
170 UMA_HISTOGRAM_TIMES("UMA.CollectExternalEventsTime", timer
.Elapsed());
174 void ExternalMetrics::ScheduleCollector() {
175 bool result
= BrowserThread::GetBlockingPool()->PostDelayedWorkerTask(
177 base::Bind(&chromeos::ExternalMetrics::CollectEventsAndReschedule
, this),
178 base::TimeDelta::FromSeconds(kExternalMetricsCollectionIntervalSeconds
));
182 } // namespace chromeos