blob: 7a73f96f416f16ed6bd4e721319e8bc52e0bdd65 [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
jar@chromium.orgc5d86fd2011-08-07 14:19:08 +090048#include "base/atomicops.h"
darin@chromium.orge585bed2011-08-06 00:34:00 +090049#include "base/base_export.h"
jar@chromium.orgae56e482010-11-04 08:36:24 +090050#include "base/gtest_prod_util.h"
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +090051#include "base/logging.h"
jar@chromium.org155b73c2009-04-11 07:29:29 +090052#include "base/time.h"
initial.commit3f4a7322008-07-27 06:49:38 +090053
brettw@chromium.org275c2ec2010-10-14 13:38:38 +090054class Pickle;
55
56namespace base {
erg@chromium.orgd9721892010-07-17 05:30:47 +090057
brettw@chromium.orge439a962011-01-02 08:16:20 +090058class Lock;
jar@chromium.orgc5d86fd2011-08-07 14:19:08 +090059//------------------------------------------------------------------------------
60// Histograms are often put in areas where they are called many many times, and
61// performance is critical. As a result, they are designed to have a very low
62// recurring cost of executing (adding additional samples). Toward that end,
63// the macros declare a static pointer to the histogram in question, and only
64// take a "slow path" to construct (or find) the histogram on the first run
65// through the macro. We leak the histograms at shutdown time so that we don't
66// have to validate using the pointers at any time during the running of the
67// process.
68
69// The following code is generally what a thread-safe static pointer
70// initializaion looks like for a histogram (after a macro is expanded). This
71// sample is an expansion (with comments) of the code for
72// HISTOGRAM_CUSTOM_COUNTS().
73
74/*
75 do {
76 // The pointer's presence indicates the initialization is complete.
77 // Initialization is idempotent, so it can safely be atomically repeated.
78 static base::subtle::AtomicWord atomic_histogram_pointer = 0;
79
80 // Acquire_Load() ensures that we acquire visibility to the pointed-to data
81 // in the histogrom.
82 base::Histogram* histogram_pointer(reinterpret_cast<base::Histogram*>(
83 base::subtle::Acquire_Load(&atomic_histogram_pointer)));
84
85 if (!histogram_pointer) {
86 // This is the slow path, which will construct OR find the matching
87 // histogram. FactoryGet includes locks on a global histogram name map
88 // and is completely thread safe.
89 histogram_pointer = base::Histogram::FactoryGet(
90 name, min, max, bucket_count, base::Histogram::kNoFlags);
91
92 // Use Release_Store to ensure that the histogram data is made available
93 // globally before we make the pointer visible.
94 // Several threads may perform this store, but the same value will be
95 // stored in all cases (for a given named/spec'ed histogram).
96 // We could do this without any barrier, since FactoryGet entered and
97 // exited a lock after construction, but this barrier makes things clear.
98 base::subtle::Release_Store(&atomic_histogram_pointer,
99 reinterpret_cast<base::subtle::AtomicWord>(histogram_pointer));
100 }
101
102 // Ensure calling contract is upheld, and the name does NOT vary.
103 DCHECK(histogram_pointer->histogram_name() == constant_histogram_name);
104
105 histogram_pointer->Add(sample);
106 } while (0);
107*/
108
109// The above pattern is repeated in several macros. The only elements that
110// vary are the invocation of the Add(sample) vs AddTime(sample), and the choice
111// of which FactoryGet method to use. The different FactoryGet methods have
112// various argument lists, so the function with its argument list is provided as
113// a macro argument here. The name is only used in a DCHECK, to assure that
114// callers don't try to vary the name of the histogram (which would tend to be
115// ignored by the one-time initialization of the histogtram_pointer).
116#define STATIC_HISTOGRAM_POINTER_BLOCK(constant_histogram_name, \
117 histogram_add_method_invocation, \
118 histogram_factory_get_invocation) \
119 do { \
120 static base::subtle::AtomicWord atomic_histogram_pointer = 0; \
121 base::Histogram* histogram_pointer(reinterpret_cast<base::Histogram*>( \
122 base::subtle::Acquire_Load(&atomic_histogram_pointer))); \
123 if (!histogram_pointer) { \
124 histogram_pointer = histogram_factory_get_invocation; \
125 base::subtle::Release_Store(&atomic_histogram_pointer, \
126 reinterpret_cast<base::subtle::AtomicWord>(histogram_pointer)); \
127 } \
128 DCHECK(histogram_pointer->histogram_name() == constant_histogram_name); \
129 histogram_pointer->histogram_add_method_invocation; \
130 } while (0)
131
brettw@chromium.orge439a962011-01-02 08:16:20 +0900132
initial.commit3f4a7322008-07-27 06:49:38 +0900133//------------------------------------------------------------------------------
134// Provide easy general purpose histogram in a macro, just like stats counters.
rvargas@google.comba686f62009-03-25 06:19:55 +0900135// The first four macros use 50 buckets.
initial.commit3f4a7322008-07-27 06:49:38 +0900136
jar@chromium.orged5238a2009-12-28 15:59:52 +0900137#define HISTOGRAM_TIMES(name, sample) HISTOGRAM_CUSTOM_TIMES( \
138 name, sample, base::TimeDelta::FromMilliseconds(1), \
139 base::TimeDelta::FromSeconds(10), 50)
initial.commit3f4a7322008-07-27 06:49:38 +0900140
jar@chromium.orged5238a2009-12-28 15:59:52 +0900141#define HISTOGRAM_COUNTS(name, sample) HISTOGRAM_CUSTOM_COUNTS( \
142 name, sample, 1, 1000000, 50)
initial.commit3f4a7322008-07-27 06:49:38 +0900143
jar@chromium.orged5238a2009-12-28 15:59:52 +0900144#define HISTOGRAM_COUNTS_100(name, sample) HISTOGRAM_CUSTOM_COUNTS( \
145 name, sample, 1, 100, 50)
cpu@google.com04d65542009-02-05 11:13:49 +0900146
jar@chromium.orged5238a2009-12-28 15:59:52 +0900147#define HISTOGRAM_COUNTS_10000(name, sample) HISTOGRAM_CUSTOM_COUNTS( \
148 name, sample, 1, 10000, 50)
rvargas@google.comba686f62009-03-25 06:19:55 +0900149
jar@chromium.orgc5d86fd2011-08-07 14:19:08 +0900150#define HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \
151 STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \
152 base::Histogram::FactoryGet(name, min, max, bucket_count, \
153 base::Histogram::kNoFlags))
jar@chromium.orga88727c2009-06-30 01:40:13 +0900154
jar@chromium.orged5238a2009-12-28 15:59:52 +0900155#define HISTOGRAM_PERCENTAGE(name, under_one_hundred) \
156 HISTOGRAM_ENUMERATION(name, under_one_hundred, 101)
jar@chromium.org775d9772009-03-14 05:29:58 +0900157
jar@chromium.org23938762009-06-21 07:32:51 +0900158// For folks that need real specific times, use this to select a precise range
159// of times you want plotted, and the number of buckets you want used.
jar@chromium.orgc5d86fd2011-08-07 14:19:08 +0900160#define HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \
161 STATIC_HISTOGRAM_POINTER_BLOCK(name, AddTime(sample), \
162 base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \
163 base::Histogram::kNoFlags))
jar@chromium.org373b6862009-02-02 15:50:03 +0900164
jar@chromium.orged5238a2009-12-28 15:59:52 +0900165// Support histograming of an enumerated value. The samples should always be
166// less than boundary_value.
jar@chromium.orgc5d86fd2011-08-07 14:19:08 +0900167#define HISTOGRAM_ENUMERATION(name, sample, boundary_value) \
168 STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \
169 base::LinearHistogram::FactoryGet(name, 1, boundary_value, \
170 boundary_value + 1, base::Histogram::kNoFlags))
initial.commit3f4a7322008-07-27 06:49:38 +0900171
joi@chromium.orgfd1b87b2011-05-24 22:59:58 +0900172// Support histograming of an enumerated value. Samples should be one of the
173// std::vector<int> list provided via |custom_ranges|. You can use the helper
174// function |base::CustomHistogram::ArrayToCustomRanges(samples, num_samples)|
175// to transform a C-style array of valid sample values to a std::vector<int>.
jar@chromium.orgc5d86fd2011-08-07 14:19:08 +0900176#define HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \
177 STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \
178 base::CustomHistogram::FactoryGet(name, custom_ranges, \
179 base::Histogram::kNoFlags))
jar@chromium.orged5238a2009-12-28 15:59:52 +0900180
initial.commit3f4a7322008-07-27 06:49:38 +0900181//------------------------------------------------------------------------------
182// Define Debug vs non-debug flavors of macros.
183#ifndef NDEBUG
184
185#define DHISTOGRAM_TIMES(name, sample) HISTOGRAM_TIMES(name, sample)
186#define DHISTOGRAM_COUNTS(name, sample) HISTOGRAM_COUNTS(name, sample)
jar@chromium.org775d9772009-03-14 05:29:58 +0900187#define DHISTOGRAM_PERCENTAGE(name, under_one_hundred) HISTOGRAM_PERCENTAGE(\
188 name, under_one_hundred)
jar@chromium.org23938762009-06-21 07:32:51 +0900189#define DHISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \
190 HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count)
jar@chromium.org373b6862009-02-02 15:50:03 +0900191#define DHISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) \
192 HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count)
jar@chromium.orga88727c2009-06-30 01:40:13 +0900193#define DHISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \
jar@chromium.orged5238a2009-12-28 15:59:52 +0900194 HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count)
195#define DHISTOGRAM_ENUMERATION(name, sample, boundary_value) \
196 HISTOGRAM_ENUMERATION(name, sample, boundary_value)
jar@chromium.org84320c52010-04-30 07:39:55 +0900197#define DHISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \
198 HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges)
initial.commit3f4a7322008-07-27 06:49:38 +0900199
200#else // NDEBUG
201
202#define DHISTOGRAM_TIMES(name, sample) do {} while (0)
203#define DHISTOGRAM_COUNTS(name, sample) do {} while (0)
jar@chromium.org775d9772009-03-14 05:29:58 +0900204#define DHISTOGRAM_PERCENTAGE(name, under_one_hundred) do {} while (0)
jar@chromium.org23938762009-06-21 07:32:51 +0900205#define DHISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \
206 do {} while (0)
jar@chromium.org373b6862009-02-02 15:50:03 +0900207#define DHISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) \
208 do {} while (0)
jar@chromium.orga88727c2009-06-30 01:40:13 +0900209#define DHISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \
jar@chromium.orged5238a2009-12-28 15:59:52 +0900210 do {} while (0)
211#define DHISTOGRAM_ENUMERATION(name, sample, boundary_value) do {} while (0)
jar@chromium.org84320c52010-04-30 07:39:55 +0900212#define DHISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \
213 do {} while (0)
initial.commit3f4a7322008-07-27 06:49:38 +0900214
215#endif // NDEBUG
216
217//------------------------------------------------------------------------------
218// The following macros provide typical usage scenarios for callers that wish
219// to record histogram data, and have the data submitted/uploaded via UMA.
220// Not all systems support such UMA, but if they do, the following macros
221// should work with the service.
222
jar@chromium.orged5238a2009-12-28 15:59:52 +0900223#define UMA_HISTOGRAM_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \
224 name, sample, base::TimeDelta::FromMilliseconds(1), \
225 base::TimeDelta::FromSeconds(10), 50)
initial.commit3f4a7322008-07-27 06:49:38 +0900226
jar@chromium.orged5238a2009-12-28 15:59:52 +0900227#define UMA_HISTOGRAM_MEDIUM_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \
228 name, sample, base::TimeDelta::FromMilliseconds(10), \
229 base::TimeDelta::FromMinutes(3), 50)
jar@google.coma5c410d2008-11-22 10:40:22 +0900230
initial.commit3f4a7322008-07-27 06:49:38 +0900231// Use this macro when times can routinely be much longer than 10 seconds.
jar@chromium.orged5238a2009-12-28 15:59:52 +0900232#define UMA_HISTOGRAM_LONG_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \
233 name, sample, base::TimeDelta::FromMilliseconds(1), \
234 base::TimeDelta::FromHours(1), 50)
initial.commit3f4a7322008-07-27 06:49:38 +0900235
jar@chromium.orgc5d86fd2011-08-07 14:19:08 +0900236#define UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \
237 STATIC_HISTOGRAM_POINTER_BLOCK(name, AddTime(sample), \
238 base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \
239 base::Histogram::kUmaTargetedHistogramFlag))
jar@chromium.org373b6862009-02-02 15:50:03 +0900240
jar@chromium.orged5238a2009-12-28 15:59:52 +0900241#define UMA_HISTOGRAM_COUNTS(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
242 name, sample, 1, 1000000, 50)
initial.commit3f4a7322008-07-27 06:49:38 +0900243
jar@chromium.orged5238a2009-12-28 15:59:52 +0900244#define UMA_HISTOGRAM_COUNTS_100(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
245 name, sample, 1, 100, 50)
initial.commit3f4a7322008-07-27 06:49:38 +0900246
jar@chromium.orged5238a2009-12-28 15:59:52 +0900247#define UMA_HISTOGRAM_COUNTS_10000(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
248 name, sample, 1, 10000, 50)
rvargas@google.comba686f62009-03-25 06:19:55 +0900249
jar@chromium.orgc5d86fd2011-08-07 14:19:08 +0900250#define UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \
251 STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \
252 base::Histogram::FactoryGet(name, min, max, bucket_count, \
253 base::Histogram::kUmaTargetedHistogramFlag))
jar@chromium.orga88727c2009-06-30 01:40:13 +0900254
jar@chromium.orged5238a2009-12-28 15:59:52 +0900255#define UMA_HISTOGRAM_MEMORY_KB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
256 name, sample, 1000, 500000, 50)
257
258#define UMA_HISTOGRAM_MEMORY_MB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
259 name, sample, 1, 1000, 50)
260
261#define UMA_HISTOGRAM_PERCENTAGE(name, under_one_hundred) \
262 UMA_HISTOGRAM_ENUMERATION(name, under_one_hundred, 101)
263
jar@chromium.orgc5d86fd2011-08-07 14:19:08 +0900264#define UMA_HISTOGRAM_BOOLEAN(name, sample) \
265 STATIC_HISTOGRAM_POINTER_BLOCK(name, AddBoolean(sample), \
266 base::BooleanHistogram::FactoryGet(name, \
267 base::Histogram::kUmaTargetedHistogramFlag))
isherman@chromium.org8cdb0212011-04-14 05:55:10 +0900268
jar@chromium.orgc5d86fd2011-08-07 14:19:08 +0900269#define UMA_HISTOGRAM_ENUMERATION(name, sample, boundary_value) \
270 STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \
271 base::LinearHistogram::FactoryGet(name, 1, boundary_value, \
272 boundary_value + 1, base::Histogram::kUmaTargetedHistogramFlag))
initial.commit3f4a7322008-07-27 06:49:38 +0900273
jar@chromium.orgc5d86fd2011-08-07 14:19:08 +0900274#define UMA_HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \
275 STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \
276 base::CustomHistogram::FactoryGet(name, custom_ranges, \
277 base::Histogram::kUmaTargetedHistogramFlag))
jar@chromium.org775d9772009-03-14 05:29:58 +0900278
initial.commit3f4a7322008-07-27 06:49:38 +0900279//------------------------------------------------------------------------------
280
jar@chromium.org84320c52010-04-30 07:39:55 +0900281class BooleanHistogram;
282class CustomHistogram;
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900283class Histogram;
284class LinearHistogram;
thestig@chromium.org05d9dd22009-04-04 03:18:55 +0900285
darin@chromium.orge585bed2011-08-06 00:34:00 +0900286class BASE_EXPORT Histogram {
initial.commit3f4a7322008-07-27 06:49:38 +0900287 public:
288 typedef int Sample; // Used for samples (and ranges of samples).
289 typedef int Count; // Used to count samples in a bucket.
290 static const Sample kSampleType_MAX = INT_MAX;
rtenneti@chromium.org6ef07b52011-03-02 17:04:57 +0900291 // Initialize maximum number of buckets in histograms as 16,384.
rtenneti@chromium.org5a0b62f2011-02-24 07:31:18 +0900292 static const size_t kBucketCount_MAX;
initial.commit3f4a7322008-07-27 06:49:38 +0900293
294 typedef std::vector<Count> Counts;
deanm@google.com18188472008-08-12 03:57:54 +0900295 typedef std::vector<Sample> Ranges;
initial.commit3f4a7322008-07-27 06:49:38 +0900296
jar@chromium.orgae56e482010-11-04 08:36:24 +0900297 // These enums are used to facilitate deserialization of renderer histograms
298 // into the browser.
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900299 enum ClassType {
300 HISTOGRAM,
301 LINEAR_HISTOGRAM,
302 BOOLEAN_HISTOGRAM,
jar@chromium.org84320c52010-04-30 07:39:55 +0900303 CUSTOM_HISTOGRAM,
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900304 NOT_VALID_IN_RENDERER
305 };
306
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900307 enum BucketLayout {
308 EXPONENTIAL,
jar@chromium.org84320c52010-04-30 07:39:55 +0900309 LINEAR,
310 CUSTOM
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900311 };
312
jar@chromium.orged5238a2009-12-28 15:59:52 +0900313 enum Flags {
314 kNoFlags = 0,
315 kUmaTargetedHistogramFlag = 0x1, // Histogram should be UMA uploaded.
316
317 // Indicate that the histogram was pickled to be sent across an IPC Channel.
318 // If we observe this flag on a histogram being aggregated into after IPC,
319 // then we are running in a single process mode, and the aggregation should
320 // not take place (as we would be aggregating back into the source
321 // histogram!).
322 kIPCSerializationSourceFlag = 0x10,
323
324 kHexRangePrintingFlag = 0x8000, // Fancy bucket-naming supported.
325 };
326
jar@chromium.orgae56e482010-11-04 08:36:24 +0900327 enum Inconsistencies {
328 NO_INCONSISTENCIES = 0x0,
329 RANGE_CHECKSUM_ERROR = 0x1,
330 BUCKET_ORDER_ERROR = 0x2,
331 COUNT_HIGH_ERROR = 0x4,
332 COUNT_LOW_ERROR = 0x8,
333
334 NEVER_EXCEEDED_VALUE = 0x10
335 };
336
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900337 struct DescriptionPair {
338 Sample sample;
339 const char* description; // Null means end of a list of pairs.
340 };
341
initial.commit3f4a7322008-07-27 06:49:38 +0900342 //----------------------------------------------------------------------------
343 // Statistic values, developed over the life of the histogram.
344
darin@chromium.orge585bed2011-08-06 00:34:00 +0900345 class BASE_EXPORT SampleSet {
initial.commit3f4a7322008-07-27 06:49:38 +0900346 public:
347 explicit SampleSet();
erg@google.com71915232010-09-29 07:54:58 +0900348 ~SampleSet();
349
initial.commit3f4a7322008-07-27 06:49:38 +0900350 // Adjust size of counts_ for use with given histogram.
351 void Resize(const Histogram& histogram);
352 void CheckSize(const Histogram& histogram) const;
353
354 // Accessor for histogram to make routine additions.
355 void Accumulate(Sample value, Count count, size_t index);
356
357 // Accessor methods.
358 Count counts(size_t i) const { return counts_[i]; }
jar@chromium.org373b6862009-02-02 15:50:03 +0900359 Count TotalCount() const;
initial.commit3f4a7322008-07-27 06:49:38 +0900360 int64 sum() const { return sum_; }
jar@chromium.orgae56e482010-11-04 08:36:24 +0900361 int64 redundant_count() const { return redundant_count_; }
initial.commit3f4a7322008-07-27 06:49:38 +0900362
363 // Arithmetic manipulation of corresponding elements of the set.
364 void Add(const SampleSet& other);
365 void Subtract(const SampleSet& other);
366
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900367 bool Serialize(Pickle* pickle) const;
368 bool Deserialize(void** iter, const Pickle& pickle);
369
rvargas@google.com644c9122008-09-25 08:51:25 +0900370 protected:
initial.commit3f4a7322008-07-27 06:49:38 +0900371 // Actual histogram data is stored in buckets, showing the count of values
372 // that fit into each bucket.
373 Counts counts_;
374
375 // Save simple stats locally. Note that this MIGHT get done in base class
376 // without shared memory at some point.
377 int64 sum_; // sum of samples.
jar@chromium.orgae56e482010-11-04 08:36:24 +0900378
379 private:
380 // Allow tests to corrupt our innards for testing purposes.
381 FRIEND_TEST(HistogramTest, CorruptSampleCounts);
382
383 // To help identify memory corruption, we reduntantly save the number of
384 // samples we've accumulated into all of our buckets. We can compare this
385 // count to the sum of the counts in all buckets, and detect problems. Note
386 // that due to races in histogram accumulation (if a histogram is indeed
387 // updated on several threads simultaneously), the tallies might mismatch,
388 // and also the snapshotting code may asynchronously get a mismatch (though
389 // generally either race based mismatch cause is VERY rare).
390 int64 redundant_count_;
initial.commit3f4a7322008-07-27 06:49:38 +0900391 };
jar@chromium.orgae56e482010-11-04 08:36:24 +0900392
initial.commit3f4a7322008-07-27 06:49:38 +0900393 //----------------------------------------------------------------------------
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900394 // minimum should start from 1. 0 is invalid as a minimum. 0 is an implicit
395 // default underflow bucket.
jar@chromium.org34571142011-04-05 13:48:53 +0900396 static Histogram* FactoryGet(const std::string& name,
397 Sample minimum,
398 Sample maximum,
399 size_t bucket_count,
400 Flags flags);
401 static Histogram* FactoryTimeGet(const std::string& name,
402 base::TimeDelta minimum,
403 base::TimeDelta maximum,
404 size_t bucket_count,
405 Flags flags);
initial.commit3f4a7322008-07-27 06:49:38 +0900406
jar@chromium.org155b73c2009-04-11 07:29:29 +0900407 void Add(int value);
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900408
409 // This method is an interface, used only by BooleanHistogram.
erg@google.com6e67c1d2010-07-29 02:25:28 +0900410 virtual void AddBoolean(bool value);
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900411
jar@chromium.org155b73c2009-04-11 07:29:29 +0900412 // Accept a TimeDelta to increment.
brettw@chromium.org275c2ec2010-10-14 13:38:38 +0900413 void AddTime(TimeDelta time) {
jar@chromium.org155b73c2009-04-11 07:29:29 +0900414 Add(static_cast<int>(time.InMilliseconds()));
415 }
initial.commit3f4a7322008-07-27 06:49:38 +0900416
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900417 void AddSampleSet(const SampleSet& sample);
418
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900419 // This method is an interface, used only by LinearHistogram.
erg@google.com6e67c1d2010-07-29 02:25:28 +0900420 virtual void SetRangeDescriptions(const DescriptionPair descriptions[]);
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900421
jar@google.coma5c410d2008-11-22 10:40:22 +0900422 // The following methods provide graphical histogram displays.
initial.commit3f4a7322008-07-27 06:49:38 +0900423 void WriteHTMLGraph(std::string* output) const;
424 void WriteAscii(bool graph_it, const std::string& newline,
425 std::string* output) const;
426
427 // Support generic flagging of Histograms.
428 // 0x1 Currently used to mark this histogram to be recorded by UMA..
429 // 0x8000 means print ranges in hex.
jar@chromium.orged5238a2009-12-28 15:59:52 +0900430 void SetFlags(Flags flags) { flags_ = static_cast<Flags> (flags_ | flags); }
431 void ClearFlags(Flags flags) { flags_ = static_cast<Flags>(flags_ & ~flags); }
initial.commit3f4a7322008-07-27 06:49:38 +0900432 int flags() const { return flags_; }
433
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900434 // Convenience methods for serializing/deserializing the histograms.
435 // Histograms from Renderer process are serialized and sent to the browser.
436 // Browser process reconstructs the histogram from the pickled version
437 // accumulates the browser-side shadow copy of histograms (that mirror
438 // histograms created in the renderer).
439
440 // Serialize the given snapshot of a Histogram into a String. Uses
441 // Pickle class to flatten the object.
442 static std::string SerializeHistogramInfo(const Histogram& histogram,
443 const SampleSet& snapshot);
444 // The following method accepts a list of pickled histograms and
445 // builds a histogram and updates shadow copy of histogram data in the
446 // browser process.
jar@chromium.org1ac6a112009-05-29 07:02:46 +0900447 static bool DeserializeHistogramInfo(const std::string& histogram_info);
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900448
jar@chromium.orgae56e482010-11-04 08:36:24 +0900449 // Check to see if bucket ranges, counts and tallies in the snapshot are
450 // consistent with the bucket ranges and checksums in our histogram. This can
451 // produce a false-alarm if a race occurred in the reading of the data during
452 // a SnapShot process, but should otherwise be false at all times (unless we
453 // have memory over-writes, or DRAM failures).
454 virtual Inconsistencies FindCorruption(const SampleSet& snapshot) const;
455
initial.commit3f4a7322008-07-27 06:49:38 +0900456 //----------------------------------------------------------------------------
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900457 // Accessors for factory constuction, serialization and testing.
initial.commit3f4a7322008-07-27 06:49:38 +0900458 //----------------------------------------------------------------------------
erg@google.com190e7b02010-12-10 03:25:03 +0900459 virtual ClassType histogram_type() const;
erg@chromium.orgd9721892010-07-17 05:30:47 +0900460 const std::string& histogram_name() const { return histogram_name_; }
initial.commit3f4a7322008-07-27 06:49:38 +0900461 Sample declared_min() const { return declared_min_; }
462 Sample declared_max() const { return declared_max_; }
erg@google.com190e7b02010-12-10 03:25:03 +0900463 virtual Sample ranges(size_t i) const;
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900464 uint32 range_checksum() const { return range_checksum_; }
erg@google.com190e7b02010-12-10 03:25:03 +0900465 virtual size_t bucket_count() const;
initial.commit3f4a7322008-07-27 06:49:38 +0900466 // Snapshot the current complete set of sample data.
467 // Override with atomic/locked snapshot if needed.
468 virtual void SnapshotSample(SampleSet* sample) const;
469
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900470 virtual bool HasConstructorArguments(Sample minimum, Sample maximum,
erg@google.com6e67c1d2010-07-29 02:25:28 +0900471 size_t bucket_count);
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900472
brettw@chromium.org275c2ec2010-10-14 13:38:38 +0900473 virtual bool HasConstructorTimeDeltaArguments(TimeDelta minimum,
474 TimeDelta maximum,
erg@google.com6e67c1d2010-07-29 02:25:28 +0900475 size_t bucket_count);
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900476 // Return true iff the range_checksum_ matches current ranges_ vector.
477 bool HasValidRangeChecksum() const;
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900478
initial.commit3f4a7322008-07-27 06:49:38 +0900479 protected:
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900480 Histogram(const std::string& name, Sample minimum,
481 Sample maximum, size_t bucket_count);
brettw@chromium.org275c2ec2010-10-14 13:38:38 +0900482 Histogram(const std::string& name, TimeDelta minimum,
483 TimeDelta maximum, size_t bucket_count);
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900484
485 virtual ~Histogram();
486
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900487 // Initialize ranges_ mapping.
488 void InitializeBucketRange();
489
initial.commit3f4a7322008-07-27 06:49:38 +0900490 // Method to override to skip the display of the i'th bucket if it's empty.
erg@google.com6e67c1d2010-07-29 02:25:28 +0900491 virtual bool PrintEmptyBucket(size_t index) const;
initial.commit3f4a7322008-07-27 06:49:38 +0900492
493 //----------------------------------------------------------------------------
494 // Methods to override to create histogram with different bucket widths.
495 //----------------------------------------------------------------------------
initial.commit3f4a7322008-07-27 06:49:38 +0900496 // Find bucket to increment for sample value.
497 virtual size_t BucketIndex(Sample value) const;
498 // Get normalized size, relative to the ranges_[i].
499 virtual double GetBucketSize(Count current, size_t i) const;
500
jar@chromium.orgae56e482010-11-04 08:36:24 +0900501 // Recalculate range_checksum_.
502 void ResetRangeChecksum();
503
initial.commit3f4a7322008-07-27 06:49:38 +0900504 // Return a string description of what goes in a given bucket.
505 // Most commonly this is the numeric value, but in derived classes it may
506 // be a name (or string description) given to the bucket.
507 virtual const std::string GetAsciiBucketRange(size_t it) const;
508
509 //----------------------------------------------------------------------------
510 // Methods to override to create thread safe histogram.
511 //----------------------------------------------------------------------------
512 // Update all our internal data, including histogram
513 virtual void Accumulate(Sample value, Count count, size_t index);
514
515 //----------------------------------------------------------------------------
516 // Accessors for derived classes.
517 //----------------------------------------------------------------------------
518 void SetBucketRange(size_t i, Sample value);
519
520 // Validate that ranges_ was created sensibly (top and bottom range
521 // values relate properly to the declared_min_ and declared_max_)..
522 bool ValidateBucketRanges() const;
523
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900524 virtual uint32 CalculateRangeChecksum() const;
525
initial.commit3f4a7322008-07-27 06:49:38 +0900526 private:
jar@chromium.orgae56e482010-11-04 08:36:24 +0900527 // Allow tests to corrupt our innards for testing purposes.
528 FRIEND_TEST(HistogramTest, CorruptBucketBounds);
529 FRIEND_TEST(HistogramTest, CorruptSampleCounts);
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900530 FRIEND_TEST(HistogramTest, Crc32SampleHash);
531 FRIEND_TEST(HistogramTest, Crc32TableTest);
jar@chromium.orgae56e482010-11-04 08:36:24 +0900532
jar@chromium.org34571142011-04-05 13:48:53 +0900533 friend class StatisticsRecorder; // To allow it to delete duplicates.
534
initial.commit3f4a7322008-07-27 06:49:38 +0900535 // Post constructor initialization.
536 void Initialize();
537
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900538 // Checksum function for accumulating range values into a checksum.
539 static uint32 Crc32(uint32 sum, Sample range);
jar@chromium.orgae56e482010-11-04 08:36:24 +0900540
initial.commit3f4a7322008-07-27 06:49:38 +0900541 //----------------------------------------------------------------------------
542 // Helpers for emitting Ascii graphic. Each method appends data to output.
543
544 // Find out how large the (graphically) the largest bucket will appear to be.
545 double GetPeakBucketSize(const SampleSet& snapshot) const;
546
547 // Write a common header message describing this histogram.
548 void WriteAsciiHeader(const SampleSet& snapshot,
jar@chromium.org373b6862009-02-02 15:50:03 +0900549 Count sample_count, std::string* output) const;
initial.commit3f4a7322008-07-27 06:49:38 +0900550
551 // Write information about previous, current, and next buckets.
552 // Information such as cumulative percentage, etc.
553 void WriteAsciiBucketContext(const int64 past, const Count current,
554 const int64 remaining, const size_t i,
555 std::string* output) const;
556
557 // Write textual description of the bucket contents (relative to histogram).
558 // Output is the count in the buckets, as well as the percentage.
559 void WriteAsciiBucketValue(Count current, double scaled_sum,
560 std::string* output) const;
561
562 // Produce actual graph (set of blank vs non blank char's) for a bucket.
563 void WriteAsciiBucketGraph(double current_size, double max_size,
564 std::string* output) const;
565
566 //----------------------------------------------------------------------------
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900567 // Table for generating Crc32 values.
568 static const uint32 kCrcTable[256];
569 //----------------------------------------------------------------------------
initial.commit3f4a7322008-07-27 06:49:38 +0900570 // Invariant values set at/near construction time
571
572 // ASCII version of original name given to the constructor. All identically
jar@chromium.orgf5db3682010-05-29 10:54:40 +0900573 // named instances will be coalesced cross-project.
initial.commit3f4a7322008-07-27 06:49:38 +0900574 const std::string histogram_name_;
575 Sample declared_min_; // Less than this goes into counts_[0]
576 Sample declared_max_; // Over this goes into counts_[bucket_count_ - 1].
577 size_t bucket_count_; // Dimension of counts_[].
578
579 // Flag the histogram for recording by UMA via metric_services.h.
jar@chromium.orged5238a2009-12-28 15:59:52 +0900580 Flags flags_;
initial.commit3f4a7322008-07-27 06:49:38 +0900581
582 // For each index, show the least value that can be stored in the
583 // corresponding bucket. We also append one extra element in this array,
584 // containing kSampleType_MAX, to make calculations easy.
585 // The dimension of ranges_ is bucket_count + 1.
586 Ranges ranges_;
587
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900588 // For redundancy, we store a checksum of all the sample ranges when ranges
589 // are generated. If ever there is ever a difference, then the histogram must
jar@chromium.orgae56e482010-11-04 08:36:24 +0900590 // have been corrupted.
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900591 uint32 range_checksum_;
jar@chromium.orgae56e482010-11-04 08:36:24 +0900592
initial.commit3f4a7322008-07-27 06:49:38 +0900593 // Finally, provide the state that changes with the addition of each new
594 // sample.
595 SampleSet sample_;
596
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900597 DISALLOW_COPY_AND_ASSIGN(Histogram);
initial.commit3f4a7322008-07-27 06:49:38 +0900598};
599
600//------------------------------------------------------------------------------
601
602// LinearHistogram is a more traditional histogram, with evenly spaced
603// buckets.
darin@chromium.orge585bed2011-08-06 00:34:00 +0900604class BASE_EXPORT LinearHistogram : public Histogram {
initial.commit3f4a7322008-07-27 06:49:38 +0900605 public:
erg@google.comd5fffd42011-01-08 03:06:45 +0900606 virtual ~LinearHistogram();
initial.commit3f4a7322008-07-27 06:49:38 +0900607
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900608 /* minimum should start from 1. 0 is as minimum is invalid. 0 is an implicit
609 default underflow bucket. */
jar@chromium.org34571142011-04-05 13:48:53 +0900610 static Histogram* FactoryGet(const std::string& name,
611 Sample minimum,
612 Sample maximum,
613 size_t bucket_count,
614 Flags flags);
615 static Histogram* FactoryTimeGet(const std::string& name,
616 TimeDelta minimum,
617 TimeDelta maximum,
618 size_t bucket_count,
619 Flags flags);
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900620
erg@google.comd5fffd42011-01-08 03:06:45 +0900621 // Overridden from Histogram:
622 virtual ClassType histogram_type() const;
623
624 // Store a list of number/text values for use in rendering the histogram.
625 // The last element in the array has a null in its "description" slot.
626 virtual void SetRangeDescriptions(const DescriptionPair descriptions[]);
erg@google.com71915232010-09-29 07:54:58 +0900627
initial.commit3f4a7322008-07-27 06:49:38 +0900628 protected:
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900629 LinearHistogram(const std::string& name, Sample minimum,
630 Sample maximum, size_t bucket_count);
631
brettw@chromium.org275c2ec2010-10-14 13:38:38 +0900632 LinearHistogram(const std::string& name, TimeDelta minimum,
633 TimeDelta maximum, size_t bucket_count);
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900634
initial.commit3f4a7322008-07-27 06:49:38 +0900635 // Initialize ranges_ mapping.
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900636 void InitializeBucketRange();
mmoss@google.comb16d6e02008-08-14 04:38:25 +0900637 virtual double GetBucketSize(Count current, size_t i) const;
initial.commit3f4a7322008-07-27 06:49:38 +0900638
639 // If we have a description for a bucket, then return that. Otherwise
640 // let parent class provide a (numeric) description.
641 virtual const std::string GetAsciiBucketRange(size_t i) const;
642
643 // Skip printing of name for numeric range if we have a name (and if this is
644 // an empty bucket).
645 virtual bool PrintEmptyBucket(size_t index) const;
646
647 private:
648 // For some ranges, we store a printable description of a bucket range.
649 // If there is no desciption, then GetAsciiBucketRange() uses parent class
650 // to provide a description.
651 typedef std::map<Sample, std::string> BucketDescriptionMap;
652 BucketDescriptionMap bucket_description_;
653
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900654 DISALLOW_COPY_AND_ASSIGN(LinearHistogram);
initial.commit3f4a7322008-07-27 06:49:38 +0900655};
656
abarth@chromium.org7ed364e2009-01-18 04:15:36 +0900657//------------------------------------------------------------------------------
658
659// BooleanHistogram is a histogram for booleans.
darin@chromium.orge585bed2011-08-06 00:34:00 +0900660class BASE_EXPORT BooleanHistogram : public LinearHistogram {
abarth@chromium.org7ed364e2009-01-18 04:15:36 +0900661 public:
jar@chromium.org34571142011-04-05 13:48:53 +0900662 static Histogram* FactoryGet(const std::string& name, Flags flags);
abarth@chromium.org7ed364e2009-01-18 04:15:36 +0900663
erg@google.com6e67c1d2010-07-29 02:25:28 +0900664 virtual ClassType histogram_type() const;
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900665
erg@google.com6e67c1d2010-07-29 02:25:28 +0900666 virtual void AddBoolean(bool value);
abarth@chromium.org7ed364e2009-01-18 04:15:36 +0900667
668 private:
erg@google.com6e67c1d2010-07-29 02:25:28 +0900669 explicit BooleanHistogram(const std::string& name);
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900670
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900671 DISALLOW_COPY_AND_ASSIGN(BooleanHistogram);
abarth@chromium.org7ed364e2009-01-18 04:15:36 +0900672};
initial.commit3f4a7322008-07-27 06:49:38 +0900673
674//------------------------------------------------------------------------------
jar@chromium.org84320c52010-04-30 07:39:55 +0900675
676// CustomHistogram is a histogram for a set of custom integers.
darin@chromium.orge585bed2011-08-06 00:34:00 +0900677class BASE_EXPORT CustomHistogram : public Histogram {
jar@chromium.org84320c52010-04-30 07:39:55 +0900678 public:
jar@chromium.org84320c52010-04-30 07:39:55 +0900679
jar@chromium.org34571142011-04-05 13:48:53 +0900680 static Histogram* FactoryGet(const std::string& name,
681 const std::vector<Sample>& custom_ranges,
682 Flags flags);
jar@chromium.org84320c52010-04-30 07:39:55 +0900683
erg@google.comd5fffd42011-01-08 03:06:45 +0900684 // Overridden from Histogram:
685 virtual ClassType histogram_type() const;
686
joi@chromium.orgfd1b87b2011-05-24 22:59:58 +0900687 // Helper method for transforming an array of valid enumeration values
688 // to the std::vector<int> expected by HISTOGRAM_CUSTOM_ENUMERATION.
689 // This function ensures that a guard bucket exists right after any
690 // valid sample value (unless the next higher sample is also a valid value),
691 // so that invalid samples never fall into the same bucket as valid samples.
692 static std::vector<Sample> ArrayToCustomRanges(const Sample* values,
693 size_t num_values);
694
jar@chromium.org84320c52010-04-30 07:39:55 +0900695 protected:
696 CustomHistogram(const std::string& name,
jar@chromium.orgae56e482010-11-04 08:36:24 +0900697 const std::vector<Sample>& custom_ranges);
jar@chromium.org84320c52010-04-30 07:39:55 +0900698
699 // Initialize ranges_ mapping.
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900700 void InitializedCustomBucketRange(const std::vector<Sample>& custom_ranges);
jar@chromium.org84320c52010-04-30 07:39:55 +0900701 virtual double GetBucketSize(Count current, size_t i) const;
702
jar@chromium.org84320c52010-04-30 07:39:55 +0900703 DISALLOW_COPY_AND_ASSIGN(CustomHistogram);
704};
705
706//------------------------------------------------------------------------------
initial.commit3f4a7322008-07-27 06:49:38 +0900707// StatisticsRecorder handles all histograms in the system. It provides a
708// general place for histograms to register, and supports a global API for
709// accessing (i.e., dumping, or graphing) the data in all the histograms.
710
darin@chromium.orge585bed2011-08-06 00:34:00 +0900711class BASE_EXPORT StatisticsRecorder {
initial.commit3f4a7322008-07-27 06:49:38 +0900712 public:
jar@chromium.org34571142011-04-05 13:48:53 +0900713 typedef std::vector<Histogram*> Histograms;
initial.commit3f4a7322008-07-27 06:49:38 +0900714
715 StatisticsRecorder();
716
717 ~StatisticsRecorder();
718
719 // Find out if histograms can now be registered into our list.
mad@chromium.org42f95b52010-12-23 23:40:10 +0900720 static bool IsActive();
initial.commit3f4a7322008-07-27 06:49:38 +0900721
jar@chromium.orgcfdfbef2011-03-05 15:22:24 +0900722 // Register, or add a new histogram to the collection of statistics. If an
723 // identically named histogram is already registered, then the argument
jar@chromium.org34571142011-04-05 13:48:53 +0900724 // |histogram| will deleted. The returned value is always the registered
725 // histogram (either the argument, or the pre-existing registered histogram).
726 static Histogram* RegisterOrDeleteDuplicate(Histogram* histogram);
initial.commit3f4a7322008-07-27 06:49:38 +0900727
728 // Methods for printing histograms. Only histograms which have query as
729 // a substring are written to output (an empty string will process all
730 // registered histograms).
731 static void WriteHTMLGraph(const std::string& query, std::string* output);
732 static void WriteGraph(const std::string& query, std::string* output);
733
734 // Method for extracting histograms which were marked for use by UMA.
735 static void GetHistograms(Histograms* output);
736
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900737 // Find a histogram by name. It matches the exact name. This method is thread
jar@chromium.org682dbbd2010-06-26 00:55:15 +0900738 // safe. If a matching histogram is not found, then the |histogram| is
739 // not changed.
jar@chromium.org34571142011-04-05 13:48:53 +0900740 static bool FindHistogram(const std::string& query, Histogram** histogram);
jar@chromium.orgfe4c0d12009-12-06 09:09:37 +0900741
742 static bool dump_on_exit() { return dump_on_exit_; }
initial.commit3f4a7322008-07-27 06:49:38 +0900743
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900744 static void set_dump_on_exit(bool enable) { dump_on_exit_ = enable; }
initial.commit3f4a7322008-07-27 06:49:38 +0900745
746 // GetSnapshot copies some of the pointers to registered histograms into the
747 // caller supplied vector (Histograms). Only histograms with names matching
748 // query are returned. The query must be a substring of histogram name for its
749 // pointer to be copied.
750 static void GetSnapshot(const std::string& query, Histograms* snapshot);
751
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900752
753 private:
754 // We keep all registered histograms in a map, from name to histogram.
jar@chromium.org34571142011-04-05 13:48:53 +0900755 typedef std::map<std::string, Histogram*> HistogramMap;
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900756
initial.commit3f4a7322008-07-27 06:49:38 +0900757 static HistogramMap* histograms_;
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900758
initial.commit3f4a7322008-07-27 06:49:38 +0900759 // lock protects access to the above map.
brettw@chromium.orge439a962011-01-02 08:16:20 +0900760 static base::Lock* lock_;
initial.commit3f4a7322008-07-27 06:49:38 +0900761
762 // Dump all known histograms to log.
763 static bool dump_on_exit_;
764
jar@chromium.orgbb363fd2009-02-25 15:10:17 +0900765 DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder);
initial.commit3f4a7322008-07-27 06:49:38 +0900766};
767
brettw@chromium.org275c2ec2010-10-14 13:38:38 +0900768} // namespace base
769
770#endif // BASE_METRICS_HISTOGRAM_H_