Fix breakages in https://codereview.chromium.org/1155713003/
[chromium-blink-merge.git] / chromecast / base / metrics / grouped_histogram.cc
blob831885066944047d697c1e489c1327c5dd99f1ee
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 {
17 namespace metrics {
19 namespace {
21 const char kAppNameErrorNoApp[] = "ERROR_NO_APP_REGISTERED";
23 // Current app name guarded by lock.
24 struct CurrentAppNameWithLock {
25 base::Lock lock;
26 std::string app_name;
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 {
39 const char* name;
40 int minimum;
41 int maximum;
42 size_t bucket_count;
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[] = {
51 "DNS.TotalTime",
53 1000 * 60 * 60,
54 100,
57 "Net.DNS_Resolution_And_TCP_Connection_Latency2",
59 1000 * 60 * 10,
60 100,
63 "Net.SSL_Connection_Latency2",
65 1000 * 60,
66 100,
69 "Net.TCP_Connection_Latency",
71 1000 * 60 * 10,
72 100,
75 "Net.HttpJob.TotalTime",
77 1000 * 10,
78 50,
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 {
86 public:
87 GroupedHistogram(const std::string& metric_to_override,
88 Sample minimum,
89 Sample maximum,
90 const base::BucketRanges* ranges)
91 : Histogram(metric_to_override, minimum, maximum, ranges),
92 metric_to_group_(metric_to_override),
93 minimum_(minimum),
94 maximum_(maximum),
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,
109 minimum_,
110 maximum_,
111 bucket_count_,
112 flags());
113 DCHECK(grouped_histogram);
114 grouped_histogram->Add(value);
117 private:
118 // Saved construction arguments for reconstructing the Histogram later (with
119 // a suffixed app name).
120 std::string metric_to_group_;
121 Sample minimum_;
122 Sample maximum_;
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,
135 size_t bucket_count,
136 int32 flags) {
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));
161 } // namespace
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