blob: 29004e4ec7ca59ce31d21176bd17a79d8dace744 [file] [log] [blame]
erg@google.comd5fffd42011-01-08 03:06:45 +09001// Copyright (c) 2011 The Chromium Authors. All rights reserved.
license.botf003cfe2008-08-24 09:55:55 +09002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit3f4a7322008-07-27 06:49:38 +09004
5// Histogram is an object that aggregates statistics, and can summarize them in
6// various forms, including ASCII graphical, HTML, and numerically (as a
7// vector of numbers corresponding to each of the aggregating buckets).
8
9// It supports calls to accumulate either time intervals (which are processed
10// as integral number of milliseconds), or arbitrary integral units.
11
12// The default layout of buckets is exponential. For example, buckets might
13// contain (sequentially) the count of values in the following intervals:
14// [0,1), [1,2), [2,4), [4,8), [8,16), [16,32), [32,64), [64,infinity)
15// That bucket allocation would actually result from construction of a histogram
16// for values between 1 and 64, with 8 buckets, such as:
17// Histogram count(L"some name", 1, 64, 8);
18// Note that the underflow bucket [0,1) and the overflow bucket [64,infinity)
19// are not counted by the constructor in the user supplied "bucket_count"
20// argument.
21// The above example has an exponential ratio of 2 (doubling the bucket width
22// in each consecutive bucket. The Histogram class automatically calculates
23// the smallest ratio that it can use to construct the number of buckets
24// selected in the constructor. An another example, if you had 50 buckets,
25// and millisecond time values from 1 to 10000, then the ratio between
26// consecutive bucket widths will be approximately somewhere around the 50th
27// root of 10000. This approach provides very fine grain (narrow) buckets
28// at the low end of the histogram scale, but allows the histogram to cover a
29// gigantic range with the addition of very few buckets.
30
jar@chromium.org34571142011-04-05 13:48:53 +090031// Histograms use a pattern involving a function static variable, that is a
32// pointer to a histogram. This static is explicitly initialized on any thread
33// that detects a uninitialized (NULL) pointer. The potentially racy
34// initialization is not a problem as it is always set to point to the same
35// value (i.e., the FactoryGet always returns the same value). FactoryGet
36// is also completely thread safe, which results in a completely thread safe,
37// and relatively fast, set of counters. To avoid races at shutdown, the static
38// pointer is NOT deleted, and we leak the histograms at process termination.
39
brettw@chromium.org275c2ec2010-10-14 13:38:38 +090040#ifndef BASE_METRICS_HISTOGRAM_H_
41#define BASE_METRICS_HISTOGRAM_H_
thakis@chromium.org01d14522010-07-27 08:08:24 +090042#pragma once
initial.commit3f4a7322008-07-27 06:49:38 +090043
44#include <map>
45#include <string>
46#include <vector>
47
rvargas@google.come106ef62011-03-26 03:48:03 +090048#include "base/base_api.h"
jar@chromium.orgae56e482010-11-04 08:36:24 +090049#include "base/gtest_prod_util.h"
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +090050#include "base/logging.h"
jar@chromium.org155b73c2009-04-11 07:29:29 +090051#include "base/time.h"
initial.commit3f4a7322008-07-27 06:49:38 +090052
brettw@chromium.org275c2ec2010-10-14 13:38:38 +090053class Pickle;
54
55namespace base {
erg@chromium.orgd9721892010-07-17 05:30:47 +090056
brettw@chromium.orge439a962011-01-02 08:16:20 +090057class Lock;
58
initial.commit3f4a7322008-07-27 06:49:38 +090059//------------------------------------------------------------------------------
60// Provide easy general purpose histogram in a macro, just like stats counters.
rvargas@google.comba686f62009-03-25 06:19:55 +090061// The first four macros use 50 buckets.
initial.commit3f4a7322008-07-27 06:49:38 +090062
jar@chromium.orged5238a2009-12-28 15:59:52 +090063#define HISTOGRAM_TIMES(name, sample) HISTOGRAM_CUSTOM_TIMES( \
64 name, sample, base::TimeDelta::FromMilliseconds(1), \
65 base::TimeDelta::FromSeconds(10), 50)
initial.commit3f4a7322008-07-27 06:49:38 +090066
jar@chromium.orged5238a2009-12-28 15:59:52 +090067#define HISTOGRAM_COUNTS(name, sample) HISTOGRAM_CUSTOM_COUNTS( \
68 name, sample, 1, 1000000, 50)
initial.commit3f4a7322008-07-27 06:49:38 +090069
jar@chromium.orged5238a2009-12-28 15:59:52 +090070#define HISTOGRAM_COUNTS_100(name, sample) HISTOGRAM_CUSTOM_COUNTS( \
71 name, sample, 1, 100, 50)
cpu@google.com04d65542009-02-05 11:13:49 +090072
jar@chromium.orged5238a2009-12-28 15:59:52 +090073#define HISTOGRAM_COUNTS_10000(name, sample) HISTOGRAM_CUSTOM_COUNTS( \
74 name, sample, 1, 10000, 50)
rvargas@google.comba686f62009-03-25 06:19:55 +090075
jar@chromium.orga88727c2009-06-30 01:40:13 +090076#define HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \
jar@chromium.org34571142011-04-05 13:48:53 +090077 static base::Histogram* counter(NULL); \
78 if (!counter) \
79 counter = base::Histogram::FactoryGet(name, min, max, bucket_count, \
80 base::Histogram::kNoFlags); \
jar@chromium.orgf0eb2282010-05-08 04:19:43 +090081 DCHECK_EQ(name, counter->histogram_name()); \
jar@chromium.org34571142011-04-05 13:48:53 +090082 counter->Add(sample); \
jar@chromium.orga88727c2009-06-30 01:40:13 +090083 } while (0)
84
jar@chromium.orged5238a2009-12-28 15:59:52 +090085#define HISTOGRAM_PERCENTAGE(name, under_one_hundred) \
86 HISTOGRAM_ENUMERATION(name, under_one_hundred, 101)
jar@chromium.org775d9772009-03-14 05:29:58 +090087
jar@chromium.org23938762009-06-21 07:32:51 +090088// For folks that need real specific times, use this to select a precise range
89// of times you want plotted, and the number of buckets you want used.
90#define HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \
jar@chromium.org34571142011-04-05 13:48:53 +090091 static base::Histogram* counter(NULL); \
92 if (!counter) \
93 counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \
94 base::Histogram::kNoFlags); \
jar@chromium.orgf0eb2282010-05-08 04:19:43 +090095 DCHECK_EQ(name, counter->histogram_name()); \
jar@chromium.org34571142011-04-05 13:48:53 +090096 counter->AddTime(sample); \
jar@chromium.org23938762009-06-21 07:32:51 +090097 } while (0)
98
99// DO NOT USE THIS. It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES.
jar@chromium.org373b6862009-02-02 15:50:03 +0900100#define HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \
jar@chromium.org34571142011-04-05 13:48:53 +0900101 static base::Histogram* counter(NULL); \
102 if (!counter) \
103 counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \
104 base::Histogram::kNoFlags); \
jar@chromium.orgf0eb2282010-05-08 04:19:43 +0900105 DCHECK_EQ(name, counter->histogram_name()); \
jar@chromium.org34571142011-04-05 13:48:53 +0900106 if ((sample) < (max)) counter->AddTime(sample); \
jar@chromium.org373b6862009-02-02 15:50:03 +0900107 } while (0)
108
jar@chromium.orged5238a2009-12-28 15:59:52 +0900109// Support histograming of an enumerated value. The samples should always be
110// less than boundary_value.
jar@chromium.orged5238a2009-12-28 15:59:52 +0900111#define HISTOGRAM_ENUMERATION(name, sample, boundary_value) do { \
jar@chromium.org34571142011-04-05 13:48:53 +0900112 static base::Histogram* counter(NULL); \
113 if (!counter) \
114 counter = base::LinearHistogram::FactoryGet(name, 1, boundary_value, \
115 boundary_value + 1, base::Histogram::kNoFlags); \
jar@chromium.orgf0eb2282010-05-08 04:19:43 +0900116 DCHECK_EQ(name, counter->histogram_name()); \
jar@chromium.org34571142011-04-05 13:48:53 +0900117 counter->Add(sample); \
initial.commit3f4a7322008-07-27 06:49:38 +0900118 } while (0)
119
joi@chromium.orgfd1b87b2011-05-24 22:59:58 +0900120// Support histograming of an enumerated value. Samples should be one of the
121// std::vector<int> list provided via |custom_ranges|. You can use the helper
122// function |base::CustomHistogram::ArrayToCustomRanges(samples, num_samples)|
123// to transform a C-style array of valid sample values to a std::vector<int>.
jar@chromium.org84320c52010-04-30 07:39:55 +0900124#define HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) do { \
jar@chromium.org34571142011-04-05 13:48:53 +0900125 static base::Histogram* counter(NULL); \
126 if (!counter) \
127 counter = base::CustomHistogram::FactoryGet(name, custom_ranges, \
128 base::Histogram::kNoFlags); \
jar@chromium.orgf0eb2282010-05-08 04:19:43 +0900129 DCHECK_EQ(name, counter->histogram_name()); \
jar@chromium.org34571142011-04-05 13:48:53 +0900130 counter->Add(sample); \
jar@chromium.org84320c52010-04-30 07:39:55 +0900131 } while (0)
132
jar@chromium.orged5238a2009-12-28 15:59:52 +0900133
initial.commit3f4a7322008-07-27 06:49:38 +0900134//------------------------------------------------------------------------------
135// Define Debug vs non-debug flavors of macros.
136#ifndef NDEBUG
137
138#define DHISTOGRAM_TIMES(name, sample) HISTOGRAM_TIMES(name, sample)
139#define DHISTOGRAM_COUNTS(name, sample) HISTOGRAM_COUNTS(name, sample)
jar@chromium.org775d9772009-03-14 05:29:58 +0900140#define DHISTOGRAM_PERCENTAGE(name, under_one_hundred) HISTOGRAM_PERCENTAGE(\
141 name, under_one_hundred)
jar@chromium.org23938762009-06-21 07:32:51 +0900142#define DHISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \
143 HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count)
jar@chromium.org373b6862009-02-02 15:50:03 +0900144#define DHISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) \
145 HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count)
jar@chromium.orga88727c2009-06-30 01:40:13 +0900146#define DHISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \
jar@chromium.orged5238a2009-12-28 15:59:52 +0900147 HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count)
148#define DHISTOGRAM_ENUMERATION(name, sample, boundary_value) \
149 HISTOGRAM_ENUMERATION(name, sample, boundary_value)
jar@chromium.org84320c52010-04-30 07:39:55 +0900150#define DHISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \
151 HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges)
initial.commit3f4a7322008-07-27 06:49:38 +0900152
153#else // NDEBUG
154
155#define DHISTOGRAM_TIMES(name, sample) do {} while (0)
156#define DHISTOGRAM_COUNTS(name, sample) do {} while (0)
jar@chromium.org775d9772009-03-14 05:29:58 +0900157#define DHISTOGRAM_PERCENTAGE(name, under_one_hundred) do {} while (0)
jar@chromium.org23938762009-06-21 07:32:51 +0900158#define DHISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \
159 do {} while (0)
jar@chromium.org373b6862009-02-02 15:50:03 +0900160#define DHISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) \
161 do {} while (0)
jar@chromium.orga88727c2009-06-30 01:40:13 +0900162#define DHISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \
jar@chromium.orged5238a2009-12-28 15:59:52 +0900163 do {} while (0)
164#define DHISTOGRAM_ENUMERATION(name, sample, boundary_value) do {} while (0)
jar@chromium.org84320c52010-04-30 07:39:55 +0900165#define DHISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \
166 do {} while (0)
initial.commit3f4a7322008-07-27 06:49:38 +0900167
168#endif // NDEBUG
169
170//------------------------------------------------------------------------------
171// The following macros provide typical usage scenarios for callers that wish
172// to record histogram data, and have the data submitted/uploaded via UMA.
173// Not all systems support such UMA, but if they do, the following macros
174// should work with the service.
175
jar@chromium.orged5238a2009-12-28 15:59:52 +0900176#define UMA_HISTOGRAM_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \
177 name, sample, base::TimeDelta::FromMilliseconds(1), \
178 base::TimeDelta::FromSeconds(10), 50)
initial.commit3f4a7322008-07-27 06:49:38 +0900179
jar@chromium.orged5238a2009-12-28 15:59:52 +0900180#define UMA_HISTOGRAM_MEDIUM_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \
181 name, sample, base::TimeDelta::FromMilliseconds(10), \
182 base::TimeDelta::FromMinutes(3), 50)
jar@google.coma5c410d2008-11-22 10:40:22 +0900183
initial.commit3f4a7322008-07-27 06:49:38 +0900184// Use this macro when times can routinely be much longer than 10 seconds.
jar@chromium.orged5238a2009-12-28 15:59:52 +0900185#define UMA_HISTOGRAM_LONG_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \
186 name, sample, base::TimeDelta::FromMilliseconds(1), \
187 base::TimeDelta::FromHours(1), 50)
initial.commit3f4a7322008-07-27 06:49:38 +0900188
jar@chromium.org23938762009-06-21 07:32:51 +0900189#define UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \
jar@chromium.org34571142011-04-05 13:48:53 +0900190 static base::Histogram* counter(NULL); \
191 if (!counter) \
192 counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \
brettw@chromium.org275c2ec2010-10-14 13:38:38 +0900193 base::Histogram::kUmaTargetedHistogramFlag); \
jar@chromium.orgf0eb2282010-05-08 04:19:43 +0900194 DCHECK_EQ(name, counter->histogram_name()); \
jar@chromium.org34571142011-04-05 13:48:53 +0900195 counter->AddTime(sample); \
jar@chromium.org23938762009-06-21 07:32:51 +0900196 } while (0)
197
jar@chromium.orged5238a2009-12-28 15:59:52 +0900198// DO NOT USE THIS. It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES.
jar@chromium.org373b6862009-02-02 15:50:03 +0900199#define UMA_HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \
jar@chromium.org34571142011-04-05 13:48:53 +0900200 static base::Histogram* counter(NULL); \
201 if (!counter) \
202 counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \
203 base::Histogram::kUmaTargetedHistogramFlag); \
jar@chromium.orgf0eb2282010-05-08 04:19:43 +0900204 DCHECK_EQ(name, counter->histogram_name()); \
jar@chromium.org34571142011-04-05 13:48:53 +0900205 if ((sample) < (max)) counter->AddTime(sample); \
jar@chromium.org373b6862009-02-02 15:50:03 +0900206 } while (0)
207
jar@chromium.orged5238a2009-12-28 15:59:52 +0900208#define UMA_HISTOGRAM_COUNTS(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
209 name, sample, 1, 1000000, 50)
initial.commit3f4a7322008-07-27 06:49:38 +0900210
jar@chromium.orged5238a2009-12-28 15:59:52 +0900211#define UMA_HISTOGRAM_COUNTS_100(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
212 name, sample, 1, 100, 50)
initial.commit3f4a7322008-07-27 06:49:38 +0900213
jar@chromium.orged5238a2009-12-28 15:59:52 +0900214#define UMA_HISTOGRAM_COUNTS_10000(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
215 name, sample, 1, 10000, 50)
rvargas@google.comba686f62009-03-25 06:19:55 +0900216
jar@chromium.orga88727c2009-06-30 01:40:13 +0900217#define UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \
jar@chromium.org34571142011-04-05 13:48:53 +0900218 static base::Histogram* counter(NULL); \
219 if (!counter) \
220 counter = base::Histogram::FactoryGet(name, min, max, bucket_count, \
221 base::Histogram::kUmaTargetedHistogramFlag); \
jar@chromium.orgf0eb2282010-05-08 04:19:43 +0900222 DCHECK_EQ(name, counter->histogram_name()); \
jar@chromium.org34571142011-04-05 13:48:53 +0900223 counter->Add(sample); \
jar@chromium.orga88727c2009-06-30 01:40:13 +0900224 } while (0)
225
jar@chromium.orged5238a2009-12-28 15:59:52 +0900226#define UMA_HISTOGRAM_MEMORY_KB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
227 name, sample, 1000, 500000, 50)
228
229#define UMA_HISTOGRAM_MEMORY_MB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
230 name, sample, 1, 1000, 50)
231
232#define UMA_HISTOGRAM_PERCENTAGE(name, under_one_hundred) \
233 UMA_HISTOGRAM_ENUMERATION(name, under_one_hundred, 101)
234
isherman@chromium.org8cdb0212011-04-14 05:55:10 +0900235#define UMA_HISTOGRAM_BOOLEAN(name, sample) do { \
236 static base::Histogram* counter(NULL); \
237 if (!counter) \
238 counter = base::BooleanHistogram::FactoryGet(name, \
239 base::Histogram::kUmaTargetedHistogramFlag); \
240 DCHECK_EQ(name, counter->histogram_name()); \
241 counter->AddBoolean(sample); \
242 } while (0)
243
jar@chromium.orged5238a2009-12-28 15:59:52 +0900244#define UMA_HISTOGRAM_ENUMERATION(name, sample, boundary_value) do { \
jar@chromium.org34571142011-04-05 13:48:53 +0900245 static base::Histogram* counter(NULL); \
246 if (!counter) \
247 counter = base::LinearHistogram::FactoryGet(name, 1, boundary_value, \
248 boundary_value + 1, base::Histogram::kUmaTargetedHistogramFlag); \
jar@chromium.orgf0eb2282010-05-08 04:19:43 +0900249 DCHECK_EQ(name, counter->histogram_name()); \
jar@chromium.org34571142011-04-05 13:48:53 +0900250 counter->Add(sample); \
initial.commit3f4a7322008-07-27 06:49:38 +0900251 } while (0)
252
jar@chromium.org84320c52010-04-30 07:39:55 +0900253#define UMA_HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) do { \
jar@chromium.org34571142011-04-05 13:48:53 +0900254 static base::Histogram* counter(NULL); \
255 if (!counter) \
256 counter = base::CustomHistogram::FactoryGet(name, custom_ranges, \
257 base::Histogram::kUmaTargetedHistogramFlag); \
jar@chromium.orgf0eb2282010-05-08 04:19:43 +0900258 DCHECK_EQ(name, counter->histogram_name()); \
jar@chromium.org34571142011-04-05 13:48:53 +0900259 counter->Add(sample); \
jar@chromium.org84320c52010-04-30 07:39:55 +0900260 } while (0)
jar@chromium.org775d9772009-03-14 05:29:58 +0900261
initial.commit3f4a7322008-07-27 06:49:38 +0900262//------------------------------------------------------------------------------
263
jar@chromium.org84320c52010-04-30 07:39:55 +0900264class BooleanHistogram;
265class CustomHistogram;
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900266class Histogram;
267class LinearHistogram;
thestig@chromium.org05d9dd22009-04-04 03:18:55 +0900268
jar@chromium.org34571142011-04-05 13:48:53 +0900269class BASE_API Histogram {
initial.commit3f4a7322008-07-27 06:49:38 +0900270 public:
271 typedef int Sample; // Used for samples (and ranges of samples).
272 typedef int Count; // Used to count samples in a bucket.
273 static const Sample kSampleType_MAX = INT_MAX;
rtenneti@chromium.org6ef07b52011-03-02 17:04:57 +0900274 // Initialize maximum number of buckets in histograms as 16,384.
rtenneti@chromium.org5a0b62f2011-02-24 07:31:18 +0900275 static const size_t kBucketCount_MAX;
initial.commit3f4a7322008-07-27 06:49:38 +0900276
277 typedef std::vector<Count> Counts;
deanm@google.com18188472008-08-12 03:57:54 +0900278 typedef std::vector<Sample> Ranges;
initial.commit3f4a7322008-07-27 06:49:38 +0900279
jar@chromium.orgae56e482010-11-04 08:36:24 +0900280 // These enums are used to facilitate deserialization of renderer histograms
281 // into the browser.
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900282 enum ClassType {
283 HISTOGRAM,
284 LINEAR_HISTOGRAM,
285 BOOLEAN_HISTOGRAM,
jar@chromium.org84320c52010-04-30 07:39:55 +0900286 CUSTOM_HISTOGRAM,
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900287 NOT_VALID_IN_RENDERER
288 };
289
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900290 enum BucketLayout {
291 EXPONENTIAL,
jar@chromium.org84320c52010-04-30 07:39:55 +0900292 LINEAR,
293 CUSTOM
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900294 };
295
jar@chromium.orged5238a2009-12-28 15:59:52 +0900296 enum Flags {
297 kNoFlags = 0,
298 kUmaTargetedHistogramFlag = 0x1, // Histogram should be UMA uploaded.
299
300 // Indicate that the histogram was pickled to be sent across an IPC Channel.
301 // If we observe this flag on a histogram being aggregated into after IPC,
302 // then we are running in a single process mode, and the aggregation should
303 // not take place (as we would be aggregating back into the source
304 // histogram!).
305 kIPCSerializationSourceFlag = 0x10,
306
307 kHexRangePrintingFlag = 0x8000, // Fancy bucket-naming supported.
308 };
309
jar@chromium.orgae56e482010-11-04 08:36:24 +0900310 enum Inconsistencies {
311 NO_INCONSISTENCIES = 0x0,
312 RANGE_CHECKSUM_ERROR = 0x1,
313 BUCKET_ORDER_ERROR = 0x2,
314 COUNT_HIGH_ERROR = 0x4,
315 COUNT_LOW_ERROR = 0x8,
316
317 NEVER_EXCEEDED_VALUE = 0x10
318 };
319
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900320 struct DescriptionPair {
321 Sample sample;
322 const char* description; // Null means end of a list of pairs.
323 };
324
initial.commit3f4a7322008-07-27 06:49:38 +0900325 //----------------------------------------------------------------------------
326 // Statistic values, developed over the life of the histogram.
327
rvargas@google.come106ef62011-03-26 03:48:03 +0900328 class BASE_API SampleSet {
initial.commit3f4a7322008-07-27 06:49:38 +0900329 public:
330 explicit SampleSet();
erg@google.com71915232010-09-29 07:54:58 +0900331 ~SampleSet();
332
initial.commit3f4a7322008-07-27 06:49:38 +0900333 // Adjust size of counts_ for use with given histogram.
334 void Resize(const Histogram& histogram);
335 void CheckSize(const Histogram& histogram) const;
336
337 // Accessor for histogram to make routine additions.
338 void Accumulate(Sample value, Count count, size_t index);
339
340 // Accessor methods.
341 Count counts(size_t i) const { return counts_[i]; }
jar@chromium.org373b6862009-02-02 15:50:03 +0900342 Count TotalCount() const;
initial.commit3f4a7322008-07-27 06:49:38 +0900343 int64 sum() const { return sum_; }
jar@chromium.orgae56e482010-11-04 08:36:24 +0900344 int64 redundant_count() const { return redundant_count_; }
initial.commit3f4a7322008-07-27 06:49:38 +0900345
346 // Arithmetic manipulation of corresponding elements of the set.
347 void Add(const SampleSet& other);
348 void Subtract(const SampleSet& other);
349
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900350 bool Serialize(Pickle* pickle) const;
351 bool Deserialize(void** iter, const Pickle& pickle);
352
rvargas@google.com644c9122008-09-25 08:51:25 +0900353 protected:
initial.commit3f4a7322008-07-27 06:49:38 +0900354 // Actual histogram data is stored in buckets, showing the count of values
355 // that fit into each bucket.
356 Counts counts_;
357
358 // Save simple stats locally. Note that this MIGHT get done in base class
359 // without shared memory at some point.
360 int64 sum_; // sum of samples.
jar@chromium.orgae56e482010-11-04 08:36:24 +0900361
362 private:
363 // Allow tests to corrupt our innards for testing purposes.
364 FRIEND_TEST(HistogramTest, CorruptSampleCounts);
365
366 // To help identify memory corruption, we reduntantly save the number of
367 // samples we've accumulated into all of our buckets. We can compare this
368 // count to the sum of the counts in all buckets, and detect problems. Note
369 // that due to races in histogram accumulation (if a histogram is indeed
370 // updated on several threads simultaneously), the tallies might mismatch,
371 // and also the snapshotting code may asynchronously get a mismatch (though
372 // generally either race based mismatch cause is VERY rare).
373 int64 redundant_count_;
initial.commit3f4a7322008-07-27 06:49:38 +0900374 };
jar@chromium.orgae56e482010-11-04 08:36:24 +0900375
initial.commit3f4a7322008-07-27 06:49:38 +0900376 //----------------------------------------------------------------------------
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900377 // minimum should start from 1. 0 is invalid as a minimum. 0 is an implicit
378 // default underflow bucket.
jar@chromium.org34571142011-04-05 13:48:53 +0900379 static Histogram* FactoryGet(const std::string& name,
380 Sample minimum,
381 Sample maximum,
382 size_t bucket_count,
383 Flags flags);
384 static Histogram* FactoryTimeGet(const std::string& name,
385 base::TimeDelta minimum,
386 base::TimeDelta maximum,
387 size_t bucket_count,
388 Flags flags);
initial.commit3f4a7322008-07-27 06:49:38 +0900389
jar@chromium.org155b73c2009-04-11 07:29:29 +0900390 void Add(int value);
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900391
392 // This method is an interface, used only by BooleanHistogram.
erg@google.com6e67c1d2010-07-29 02:25:28 +0900393 virtual void AddBoolean(bool value);
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900394
jar@chromium.org155b73c2009-04-11 07:29:29 +0900395 // Accept a TimeDelta to increment.
brettw@chromium.org275c2ec2010-10-14 13:38:38 +0900396 void AddTime(TimeDelta time) {
jar@chromium.org155b73c2009-04-11 07:29:29 +0900397 Add(static_cast<int>(time.InMilliseconds()));
398 }
initial.commit3f4a7322008-07-27 06:49:38 +0900399
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900400 void AddSampleSet(const SampleSet& sample);
401
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900402 // This method is an interface, used only by LinearHistogram.
erg@google.com6e67c1d2010-07-29 02:25:28 +0900403 virtual void SetRangeDescriptions(const DescriptionPair descriptions[]);
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900404
jar@google.coma5c410d2008-11-22 10:40:22 +0900405 // The following methods provide graphical histogram displays.
initial.commit3f4a7322008-07-27 06:49:38 +0900406 void WriteHTMLGraph(std::string* output) const;
407 void WriteAscii(bool graph_it, const std::string& newline,
408 std::string* output) const;
409
410 // Support generic flagging of Histograms.
411 // 0x1 Currently used to mark this histogram to be recorded by UMA..
412 // 0x8000 means print ranges in hex.
jar@chromium.orged5238a2009-12-28 15:59:52 +0900413 void SetFlags(Flags flags) { flags_ = static_cast<Flags> (flags_ | flags); }
414 void ClearFlags(Flags flags) { flags_ = static_cast<Flags>(flags_ & ~flags); }
initial.commit3f4a7322008-07-27 06:49:38 +0900415 int flags() const { return flags_; }
416
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900417 // Convenience methods for serializing/deserializing the histograms.
418 // Histograms from Renderer process are serialized and sent to the browser.
419 // Browser process reconstructs the histogram from the pickled version
420 // accumulates the browser-side shadow copy of histograms (that mirror
421 // histograms created in the renderer).
422
423 // Serialize the given snapshot of a Histogram into a String. Uses
424 // Pickle class to flatten the object.
425 static std::string SerializeHistogramInfo(const Histogram& histogram,
426 const SampleSet& snapshot);
427 // The following method accepts a list of pickled histograms and
428 // builds a histogram and updates shadow copy of histogram data in the
429 // browser process.
jar@chromium.org1ac6a112009-05-29 07:02:46 +0900430 static bool DeserializeHistogramInfo(const std::string& histogram_info);
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900431
jar@chromium.orgae56e482010-11-04 08:36:24 +0900432 // Check to see if bucket ranges, counts and tallies in the snapshot are
433 // consistent with the bucket ranges and checksums in our histogram. This can
434 // produce a false-alarm if a race occurred in the reading of the data during
435 // a SnapShot process, but should otherwise be false at all times (unless we
436 // have memory over-writes, or DRAM failures).
437 virtual Inconsistencies FindCorruption(const SampleSet& snapshot) const;
438
initial.commit3f4a7322008-07-27 06:49:38 +0900439 //----------------------------------------------------------------------------
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900440 // Accessors for factory constuction, serialization and testing.
initial.commit3f4a7322008-07-27 06:49:38 +0900441 //----------------------------------------------------------------------------
erg@google.com190e7b02010-12-10 03:25:03 +0900442 virtual ClassType histogram_type() const;
erg@chromium.orgd9721892010-07-17 05:30:47 +0900443 const std::string& histogram_name() const { return histogram_name_; }
initial.commit3f4a7322008-07-27 06:49:38 +0900444 Sample declared_min() const { return declared_min_; }
445 Sample declared_max() const { return declared_max_; }
erg@google.com190e7b02010-12-10 03:25:03 +0900446 virtual Sample ranges(size_t i) const;
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900447 uint32 range_checksum() const { return range_checksum_; }
erg@google.com190e7b02010-12-10 03:25:03 +0900448 virtual size_t bucket_count() const;
initial.commit3f4a7322008-07-27 06:49:38 +0900449 // Snapshot the current complete set of sample data.
450 // Override with atomic/locked snapshot if needed.
451 virtual void SnapshotSample(SampleSet* sample) const;
452
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900453 virtual bool HasConstructorArguments(Sample minimum, Sample maximum,
erg@google.com6e67c1d2010-07-29 02:25:28 +0900454 size_t bucket_count);
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900455
brettw@chromium.org275c2ec2010-10-14 13:38:38 +0900456 virtual bool HasConstructorTimeDeltaArguments(TimeDelta minimum,
457 TimeDelta maximum,
erg@google.com6e67c1d2010-07-29 02:25:28 +0900458 size_t bucket_count);
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900459 // Return true iff the range_checksum_ matches current ranges_ vector.
460 bool HasValidRangeChecksum() const;
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900461
initial.commit3f4a7322008-07-27 06:49:38 +0900462 protected:
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900463 Histogram(const std::string& name, Sample minimum,
464 Sample maximum, size_t bucket_count);
brettw@chromium.org275c2ec2010-10-14 13:38:38 +0900465 Histogram(const std::string& name, TimeDelta minimum,
466 TimeDelta maximum, size_t bucket_count);
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900467
468 virtual ~Histogram();
469
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900470 // Initialize ranges_ mapping.
471 void InitializeBucketRange();
472
initial.commit3f4a7322008-07-27 06:49:38 +0900473 // Method to override to skip the display of the i'th bucket if it's empty.
erg@google.com6e67c1d2010-07-29 02:25:28 +0900474 virtual bool PrintEmptyBucket(size_t index) const;
initial.commit3f4a7322008-07-27 06:49:38 +0900475
476 //----------------------------------------------------------------------------
477 // Methods to override to create histogram with different bucket widths.
478 //----------------------------------------------------------------------------
initial.commit3f4a7322008-07-27 06:49:38 +0900479 // Find bucket to increment for sample value.
480 virtual size_t BucketIndex(Sample value) const;
481 // Get normalized size, relative to the ranges_[i].
482 virtual double GetBucketSize(Count current, size_t i) const;
483
jar@chromium.orgae56e482010-11-04 08:36:24 +0900484 // Recalculate range_checksum_.
485 void ResetRangeChecksum();
486
initial.commit3f4a7322008-07-27 06:49:38 +0900487 // Return a string description of what goes in a given bucket.
488 // Most commonly this is the numeric value, but in derived classes it may
489 // be a name (or string description) given to the bucket.
490 virtual const std::string GetAsciiBucketRange(size_t it) const;
491
492 //----------------------------------------------------------------------------
493 // Methods to override to create thread safe histogram.
494 //----------------------------------------------------------------------------
495 // Update all our internal data, including histogram
496 virtual void Accumulate(Sample value, Count count, size_t index);
497
498 //----------------------------------------------------------------------------
499 // Accessors for derived classes.
500 //----------------------------------------------------------------------------
501 void SetBucketRange(size_t i, Sample value);
502
503 // Validate that ranges_ was created sensibly (top and bottom range
504 // values relate properly to the declared_min_ and declared_max_)..
505 bool ValidateBucketRanges() const;
506
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900507 virtual uint32 CalculateRangeChecksum() const;
508
initial.commit3f4a7322008-07-27 06:49:38 +0900509 private:
jar@chromium.orgae56e482010-11-04 08:36:24 +0900510 // Allow tests to corrupt our innards for testing purposes.
511 FRIEND_TEST(HistogramTest, CorruptBucketBounds);
512 FRIEND_TEST(HistogramTest, CorruptSampleCounts);
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900513 FRIEND_TEST(HistogramTest, Crc32SampleHash);
514 FRIEND_TEST(HistogramTest, Crc32TableTest);
jar@chromium.orgae56e482010-11-04 08:36:24 +0900515
jar@chromium.org34571142011-04-05 13:48:53 +0900516 friend class StatisticsRecorder; // To allow it to delete duplicates.
517
initial.commit3f4a7322008-07-27 06:49:38 +0900518 // Post constructor initialization.
519 void Initialize();
520
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900521 // Checksum function for accumulating range values into a checksum.
522 static uint32 Crc32(uint32 sum, Sample range);
jar@chromium.orgae56e482010-11-04 08:36:24 +0900523
initial.commit3f4a7322008-07-27 06:49:38 +0900524 //----------------------------------------------------------------------------
525 // Helpers for emitting Ascii graphic. Each method appends data to output.
526
527 // Find out how large the (graphically) the largest bucket will appear to be.
528 double GetPeakBucketSize(const SampleSet& snapshot) const;
529
530 // Write a common header message describing this histogram.
531 void WriteAsciiHeader(const SampleSet& snapshot,
jar@chromium.org373b6862009-02-02 15:50:03 +0900532 Count sample_count, std::string* output) const;
initial.commit3f4a7322008-07-27 06:49:38 +0900533
534 // Write information about previous, current, and next buckets.
535 // Information such as cumulative percentage, etc.
536 void WriteAsciiBucketContext(const int64 past, const Count current,
537 const int64 remaining, const size_t i,
538 std::string* output) const;
539
540 // Write textual description of the bucket contents (relative to histogram).
541 // Output is the count in the buckets, as well as the percentage.
542 void WriteAsciiBucketValue(Count current, double scaled_sum,
543 std::string* output) const;
544
545 // Produce actual graph (set of blank vs non blank char's) for a bucket.
546 void WriteAsciiBucketGraph(double current_size, double max_size,
547 std::string* output) const;
548
549 //----------------------------------------------------------------------------
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900550 // Table for generating Crc32 values.
551 static const uint32 kCrcTable[256];
552 //----------------------------------------------------------------------------
initial.commit3f4a7322008-07-27 06:49:38 +0900553 // Invariant values set at/near construction time
554
555 // ASCII version of original name given to the constructor. All identically
jar@chromium.orgf5db3682010-05-29 10:54:40 +0900556 // named instances will be coalesced cross-project.
initial.commit3f4a7322008-07-27 06:49:38 +0900557 const std::string histogram_name_;
558 Sample declared_min_; // Less than this goes into counts_[0]
559 Sample declared_max_; // Over this goes into counts_[bucket_count_ - 1].
560 size_t bucket_count_; // Dimension of counts_[].
561
562 // Flag the histogram for recording by UMA via metric_services.h.
jar@chromium.orged5238a2009-12-28 15:59:52 +0900563 Flags flags_;
initial.commit3f4a7322008-07-27 06:49:38 +0900564
565 // For each index, show the least value that can be stored in the
566 // corresponding bucket. We also append one extra element in this array,
567 // containing kSampleType_MAX, to make calculations easy.
568 // The dimension of ranges_ is bucket_count + 1.
569 Ranges ranges_;
570
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900571 // For redundancy, we store a checksum of all the sample ranges when ranges
572 // are generated. If ever there is ever a difference, then the histogram must
jar@chromium.orgae56e482010-11-04 08:36:24 +0900573 // have been corrupted.
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900574 uint32 range_checksum_;
jar@chromium.orgae56e482010-11-04 08:36:24 +0900575
initial.commit3f4a7322008-07-27 06:49:38 +0900576 // Finally, provide the state that changes with the addition of each new
577 // sample.
578 SampleSet sample_;
579
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900580 DISALLOW_COPY_AND_ASSIGN(Histogram);
initial.commit3f4a7322008-07-27 06:49:38 +0900581};
582
583//------------------------------------------------------------------------------
584
585// LinearHistogram is a more traditional histogram, with evenly spaced
586// buckets.
rvargas@google.come106ef62011-03-26 03:48:03 +0900587class BASE_API LinearHistogram : public Histogram {
initial.commit3f4a7322008-07-27 06:49:38 +0900588 public:
erg@google.comd5fffd42011-01-08 03:06:45 +0900589 virtual ~LinearHistogram();
initial.commit3f4a7322008-07-27 06:49:38 +0900590
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900591 /* minimum should start from 1. 0 is as minimum is invalid. 0 is an implicit
592 default underflow bucket. */
jar@chromium.org34571142011-04-05 13:48:53 +0900593 static Histogram* FactoryGet(const std::string& name,
594 Sample minimum,
595 Sample maximum,
596 size_t bucket_count,
597 Flags flags);
598 static Histogram* FactoryTimeGet(const std::string& name,
599 TimeDelta minimum,
600 TimeDelta maximum,
601 size_t bucket_count,
602 Flags flags);
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900603
erg@google.comd5fffd42011-01-08 03:06:45 +0900604 // Overridden from Histogram:
605 virtual ClassType histogram_type() const;
606
607 // Store a list of number/text values for use in rendering the histogram.
608 // The last element in the array has a null in its "description" slot.
609 virtual void SetRangeDescriptions(const DescriptionPair descriptions[]);
erg@google.com71915232010-09-29 07:54:58 +0900610
initial.commit3f4a7322008-07-27 06:49:38 +0900611 protected:
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900612 LinearHistogram(const std::string& name, Sample minimum,
613 Sample maximum, size_t bucket_count);
614
brettw@chromium.org275c2ec2010-10-14 13:38:38 +0900615 LinearHistogram(const std::string& name, TimeDelta minimum,
616 TimeDelta maximum, size_t bucket_count);
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900617
initial.commit3f4a7322008-07-27 06:49:38 +0900618 // Initialize ranges_ mapping.
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900619 void InitializeBucketRange();
mmoss@google.comb16d6e02008-08-14 04:38:25 +0900620 virtual double GetBucketSize(Count current, size_t i) const;
initial.commit3f4a7322008-07-27 06:49:38 +0900621
622 // If we have a description for a bucket, then return that. Otherwise
623 // let parent class provide a (numeric) description.
624 virtual const std::string GetAsciiBucketRange(size_t i) const;
625
626 // Skip printing of name for numeric range if we have a name (and if this is
627 // an empty bucket).
628 virtual bool PrintEmptyBucket(size_t index) const;
629
630 private:
631 // For some ranges, we store a printable description of a bucket range.
632 // If there is no desciption, then GetAsciiBucketRange() uses parent class
633 // to provide a description.
634 typedef std::map<Sample, std::string> BucketDescriptionMap;
635 BucketDescriptionMap bucket_description_;
636
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900637 DISALLOW_COPY_AND_ASSIGN(LinearHistogram);
initial.commit3f4a7322008-07-27 06:49:38 +0900638};
639
abarth@chromium.org7ed364e2009-01-18 04:15:36 +0900640//------------------------------------------------------------------------------
641
642// BooleanHistogram is a histogram for booleans.
rvargas@google.come106ef62011-03-26 03:48:03 +0900643class BASE_API BooleanHistogram : public LinearHistogram {
abarth@chromium.org7ed364e2009-01-18 04:15:36 +0900644 public:
jar@chromium.org34571142011-04-05 13:48:53 +0900645 static Histogram* FactoryGet(const std::string& name, Flags flags);
abarth@chromium.org7ed364e2009-01-18 04:15:36 +0900646
erg@google.com6e67c1d2010-07-29 02:25:28 +0900647 virtual ClassType histogram_type() const;
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900648
erg@google.com6e67c1d2010-07-29 02:25:28 +0900649 virtual void AddBoolean(bool value);
abarth@chromium.org7ed364e2009-01-18 04:15:36 +0900650
651 private:
erg@google.com6e67c1d2010-07-29 02:25:28 +0900652 explicit BooleanHistogram(const std::string& name);
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900653
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900654 DISALLOW_COPY_AND_ASSIGN(BooleanHistogram);
abarth@chromium.org7ed364e2009-01-18 04:15:36 +0900655};
initial.commit3f4a7322008-07-27 06:49:38 +0900656
657//------------------------------------------------------------------------------
jar@chromium.org84320c52010-04-30 07:39:55 +0900658
659// CustomHistogram is a histogram for a set of custom integers.
rvargas@google.come106ef62011-03-26 03:48:03 +0900660class BASE_API CustomHistogram : public Histogram {
jar@chromium.org84320c52010-04-30 07:39:55 +0900661 public:
jar@chromium.org84320c52010-04-30 07:39:55 +0900662
jar@chromium.org34571142011-04-05 13:48:53 +0900663 static Histogram* FactoryGet(const std::string& name,
664 const std::vector<Sample>& custom_ranges,
665 Flags flags);
jar@chromium.org84320c52010-04-30 07:39:55 +0900666
erg@google.comd5fffd42011-01-08 03:06:45 +0900667 // Overridden from Histogram:
668 virtual ClassType histogram_type() const;
669
joi@chromium.orgfd1b87b2011-05-24 22:59:58 +0900670 // Helper method for transforming an array of valid enumeration values
671 // to the std::vector<int> expected by HISTOGRAM_CUSTOM_ENUMERATION.
672 // This function ensures that a guard bucket exists right after any
673 // valid sample value (unless the next higher sample is also a valid value),
674 // so that invalid samples never fall into the same bucket as valid samples.
675 static std::vector<Sample> ArrayToCustomRanges(const Sample* values,
676 size_t num_values);
677
jar@chromium.org84320c52010-04-30 07:39:55 +0900678 protected:
679 CustomHistogram(const std::string& name,
jar@chromium.orgae56e482010-11-04 08:36:24 +0900680 const std::vector<Sample>& custom_ranges);
jar@chromium.org84320c52010-04-30 07:39:55 +0900681
682 // Initialize ranges_ mapping.
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900683 void InitializedCustomBucketRange(const std::vector<Sample>& custom_ranges);
jar@chromium.org84320c52010-04-30 07:39:55 +0900684 virtual double GetBucketSize(Count current, size_t i) const;
685
jar@chromium.org84320c52010-04-30 07:39:55 +0900686 DISALLOW_COPY_AND_ASSIGN(CustomHistogram);
687};
688
689//------------------------------------------------------------------------------
initial.commit3f4a7322008-07-27 06:49:38 +0900690// StatisticsRecorder handles all histograms in the system. It provides a
691// general place for histograms to register, and supports a global API for
692// accessing (i.e., dumping, or graphing) the data in all the histograms.
693
rvargas@google.come106ef62011-03-26 03:48:03 +0900694class BASE_API StatisticsRecorder {
initial.commit3f4a7322008-07-27 06:49:38 +0900695 public:
jar@chromium.org34571142011-04-05 13:48:53 +0900696 typedef std::vector<Histogram*> Histograms;
initial.commit3f4a7322008-07-27 06:49:38 +0900697
698 StatisticsRecorder();
699
700 ~StatisticsRecorder();
701
702 // Find out if histograms can now be registered into our list.
mad@chromium.org42f95b52010-12-23 23:40:10 +0900703 static bool IsActive();
initial.commit3f4a7322008-07-27 06:49:38 +0900704
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900705 // Register, or add a new histogram to the collection of statistics. If an
706 // identically named histogram is already registered, then the argument
jar@chromium.org34571142011-04-05 13:48:53 +0900707 // |histogram| will deleted. The returned value is always the registered
708 // histogram (either the argument, or the pre-existing registered histogram).
709 static Histogram* RegisterOrDeleteDuplicate(Histogram* histogram);
initial.commit3f4a7322008-07-27 06:49:38 +0900710
711 // Methods for printing histograms. Only histograms which have query as
712 // a substring are written to output (an empty string will process all
713 // registered histograms).
714 static void WriteHTMLGraph(const std::string& query, std::string* output);
715 static void WriteGraph(const std::string& query, std::string* output);
716
717 // Method for extracting histograms which were marked for use by UMA.
718 static void GetHistograms(Histograms* output);
719
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900720 // Find a histogram by name. It matches the exact name. This method is thread
jar@chromium.org682dbbd2010-06-26 00:55:15 +0900721 // safe. If a matching histogram is not found, then the |histogram| is
722 // not changed.
jar@chromium.org34571142011-04-05 13:48:53 +0900723 static bool FindHistogram(const std::string& query, Histogram** histogram);
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900724
725 static bool dump_on_exit() { return dump_on_exit_; }
initial.commit3f4a7322008-07-27 06:49:38 +0900726
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900727 static void set_dump_on_exit(bool enable) { dump_on_exit_ = enable; }
initial.commit3f4a7322008-07-27 06:49:38 +0900728
729 // GetSnapshot copies some of the pointers to registered histograms into the
730 // caller supplied vector (Histograms). Only histograms with names matching
731 // query are returned. The query must be a substring of histogram name for its
732 // pointer to be copied.
733 static void GetSnapshot(const std::string& query, Histograms* snapshot);
734
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900735
736 private:
737 // We keep all registered histograms in a map, from name to histogram.
jar@chromium.org34571142011-04-05 13:48:53 +0900738 typedef std::map<std::string, Histogram*> HistogramMap;
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900739
initial.commit3f4a7322008-07-27 06:49:38 +0900740 static HistogramMap* histograms_;
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900741
initial.commit3f4a7322008-07-27 06:49:38 +0900742 // lock protects access to the above map.
brettw@chromium.orge439a962011-01-02 08:16:20 +0900743 static base::Lock* lock_;
initial.commit3f4a7322008-07-27 06:49:38 +0900744
745 // Dump all known histograms to log.
746 static bool dump_on_exit_;
747
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900748 DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder);
initial.commit3f4a7322008-07-27 06:49:38 +0900749};
750
brettw@chromium.org275c2ec2010-10-14 13:38:38 +0900751} // namespace base
752
753#endif // BASE_METRICS_HISTOGRAM_H_