1 // Copyright 2014 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 "chromecast/base/metrics/grouped_histogram.h"
7 #include "base/lazy_instance.h"
8 #include "base/logging.h"
9 #include "base/macros.h"
10 #include "base/metrics/histogram.h"
11 #include "base/metrics/statistics_recorder.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/synchronization/lock.h"
14 #include "base/time/time.h"
16 namespace chromecast
{
21 const char kAppNameErrorNoApp
[] = "ERROR_NO_APP_REGISTERED";
23 // Current app name guarded by lock.
24 struct CurrentAppNameWithLock
{
29 base::LazyInstance
<CurrentAppNameWithLock
> g_current_app
=
30 LAZY_INSTANCE_INITIALIZER
;
32 std::string
GetAppName() {
33 base::AutoLock
lock(g_current_app
.Get().lock
);
34 const std::string
& app_name
= g_current_app
.Get().app_name
;
35 return app_name
.empty() ? kAppNameErrorNoApp
: app_name
;
38 struct HistogramArgs
{
45 // List of metrics to collect using a GroupedHistogram.
47 // When adding more Histograms to this list, find the source of the
48 // Histogram and look for the construction arguments it uses to add it in.
49 const HistogramArgs kHistogramsToGroup
[] = {
57 "Net.DNS_Resolution_And_TCP_Connection_Latency2",
63 "Net.SSL_Connection_Latency2",
69 "Net.TCP_Connection_Latency",
75 "Net.HttpJob.TotalTime",
82 // This class is used to override a Histogram to generate per-app metrics.
83 // It intercepts calls to Add() for a given metric and generates new metrics
84 // of the form "<metric-name>.<app-name>".
85 class GroupedHistogram
: public base::Histogram
{
87 GroupedHistogram(const std::string
& metric_to_override
,
90 const base::BucketRanges
* ranges
)
91 : Histogram(metric_to_override
, minimum
, maximum
, ranges
),
92 metric_to_group_(metric_to_override
),
95 bucket_count_(ranges
->bucket_count()) {
98 ~GroupedHistogram() override
{
101 // base::Histogram implementation:
102 void Add(Sample value
) override
{
103 Histogram::Add(value
);
104 std::string
name(base::StringPrintf("%s.%s",
105 histogram_name().c_str(),
106 GetAppName().c_str()));
107 HistogramBase
* grouped_histogram
=
108 base::Histogram::FactoryGet(name
,
113 DCHECK(grouped_histogram
);
114 grouped_histogram
->Add(value
);
118 // Saved construction arguments for reconstructing the Histogram later (with
119 // a suffixed app name).
120 std::string metric_to_group_
;
123 size_t bucket_count_
;
125 DISALLOW_COPY_AND_ASSIGN(GroupedHistogram
);
128 // Registers a GroupedHistogram with StatisticsRecorder. Must be called
129 // before any Histogram of the same name has been used.
130 // It acts similarly to Histogram::FactoryGet but checks that
131 // the histogram is being newly created and does not already exist.
132 void PreregisterHistogram(const std::string
& name
,
133 GroupedHistogram::Sample minimum
,
134 GroupedHistogram::Sample maximum
,
137 DCHECK(base::StatisticsRecorder::IsActive());
138 DCHECK(base::Histogram::InspectConstructionArguments(
139 name
, &minimum
, &maximum
, &bucket_count
));
140 DCHECK(!base::StatisticsRecorder::FindHistogram(name
))
141 << "Failed to preregister " << name
<< ", Histogram already exists.";
143 // To avoid racy destruction at shutdown, the following will be leaked.
144 base::BucketRanges
* ranges
= new base::BucketRanges(bucket_count
+ 1);
145 base::Histogram::InitializeBucketRanges(minimum
, maximum
, ranges
);
146 const base::BucketRanges
* registered_ranges
=
147 base::StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges
);
149 GroupedHistogram
* tentative_histogram
=
150 new GroupedHistogram(name
, minimum
, maximum
, registered_ranges
);
152 tentative_histogram
->SetFlags(flags
);
153 base::HistogramBase
* histogram
=
154 base::StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram
);
156 DCHECK_EQ(histogram
, tentative_histogram
);
157 DCHECK_EQ(base::HISTOGRAM
, histogram
->GetHistogramType());
158 DCHECK(histogram
->HasConstructionArguments(minimum
, maximum
, bucket_count
));
163 void PreregisterAllGroupedHistograms() {
164 base::StatisticsRecorder::Initialize();
165 for (size_t i
= 0; i
< arraysize(kHistogramsToGroup
); ++i
) {
166 PreregisterHistogram(
167 kHistogramsToGroup
[i
].name
,
168 kHistogramsToGroup
[i
].minimum
,
169 kHistogramsToGroup
[i
].maximum
,
170 kHistogramsToGroup
[i
].bucket_count
,
171 base::HistogramBase::kUmaTargetedHistogramFlag
);
175 void TagAppStartForGroupedHistograms(const std::string
& app_name
) {
176 base::AutoLock
lock(g_current_app
.Get().lock
);
177 g_current_app
.Get().app_name
= app_name
;
180 } // namespace metrics
181 } // namespace chromecast