13f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Histogram is an object that aggregates statistics, and can summarize them in
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// various forms, including ASCII graphical, HTML, and numerically (as a
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// vector of numbers corresponding to each of the aggregating buckets).
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// It supports calls to accumulate either time intervals (which are processed
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// as integral number of milliseconds), or arbitrary integral units.
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The default layout of buckets is exponential.  For example, buckets might
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// contain (sequentially) the count of values in the following intervals:
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// [0,1), [1,2), [2,4), [4,8), [8,16), [16,32), [32,64), [64,infinity)
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// That bucket allocation would actually result from construction of a histogram
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// for values between 1 and 64, with 8 buckets, such as:
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Histogram count(L"some name", 1, 64, 8);
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Note that the underflow bucket [0,1) and the overflow bucket [64,infinity)
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// are not counted by the constructor in the user supplied "bucket_count"
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// argument.
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The above example has an exponential ratio of 2 (doubling the bucket width
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// in each consecutive bucket.  The Histogram class automatically calculates
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the smallest ratio that it can use to construct the number of buckets
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// selected in the constructor.  An another example, if you had 50 buckets,
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// and millisecond time values from 1 to 10000, then the ratio between
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// consecutive bucket widths will be approximately somewhere around the 50th
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// root of 10000.  This approach provides very fine grain (narrow) buckets
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// at the low end of the histogram scale, but allows the histogram to cover a
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// gigantic range with the addition of very few buckets.
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Histograms use a pattern involving a function static variable, that is a
32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// pointer to a histogram.  This static is explicitly initialized on any thread
33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// that detects a uninitialized (NULL) pointer.  The potentially racy
34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// initialization is not a problem as it is always set to point to the same
35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// value (i.e., the FactoryGet always returns the same value).  FactoryGet
36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// is also completely thread safe, which results in a completely thread safe,
37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// and relatively fast, set of counters.  To avoid races at shutdown, the static
38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// pointer is NOT deleted, and we leak the histograms at process termination.
39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
40731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#ifndef BASE_METRICS_HISTOGRAM_H_
41731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#define BASE_METRICS_HISTOGRAM_H_
423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <map>
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <string>
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <vector>
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/base_api.h"
49513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/gtest_prod_util.h"
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h"
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/time.h"
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
53731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickclass Pickle;
54731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
55731df977c0511bca2206b5f333555b1205ff1f43Iain Merricknamespace base {
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
573f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenclass Lock;
583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//------------------------------------------------------------------------------
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Provide easy general purpose histogram in a macro, just like stats counters.
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The first four macros use 50 buckets.
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define HISTOGRAM_TIMES(name, sample) HISTOGRAM_CUSTOM_TIMES( \
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    name, sample, base::TimeDelta::FromMilliseconds(1), \
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    base::TimeDelta::FromSeconds(10), 50)
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define HISTOGRAM_COUNTS(name, sample) HISTOGRAM_CUSTOM_COUNTS( \
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    name, sample, 1, 1000000, 50)
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define HISTOGRAM_COUNTS_100(name, sample) HISTOGRAM_CUSTOM_COUNTS( \
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    name, sample, 1, 100, 50)
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define HISTOGRAM_COUNTS_10000(name, sample) HISTOGRAM_CUSTOM_COUNTS( \
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    name, sample, 1, 10000, 50)
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \
77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    static base::Histogram* counter(NULL); \
78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!counter) \
79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      counter = base::Histogram::FactoryGet(name, min, max, bucket_count, \
80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                            base::Histogram::kNoFlags); \
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK_EQ(name, counter->histogram_name()); \
82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    counter->Add(sample); \
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } while (0)
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define HISTOGRAM_PERCENTAGE(name, under_one_hundred) \
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    HISTOGRAM_ENUMERATION(name, under_one_hundred, 101)
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// For folks that need real specific times, use this to select a precise range
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// of times you want plotted, and the number of buckets you want used.
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \
91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    static base::Histogram* counter(NULL); \
92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!counter) \
93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \
94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                base::Histogram::kNoFlags); \
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK_EQ(name, counter->histogram_name()); \
96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    counter->AddTime(sample); \
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } while (0)
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// DO NOT USE THIS.  It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES.
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \
101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    static base::Histogram* counter(NULL); \
102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!counter) \
103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \
104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                base::Histogram::kNoFlags); \
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK_EQ(name, counter->histogram_name()); \
106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if ((sample) < (max)) counter->AddTime(sample); \
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } while (0)
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Support histograming of an enumerated value.  The samples should always be
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// less than boundary_value.
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define HISTOGRAM_ENUMERATION(name, sample, boundary_value) do { \
113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    static base::Histogram* counter(NULL); \
114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!counter) \
115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      counter = base::LinearHistogram::FactoryGet(name, 1, boundary_value, \
116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          boundary_value + 1, base::Histogram::kNoFlags); \
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK_EQ(name, counter->histogram_name()); \
118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    counter->Add(sample); \
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } while (0)
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) do { \
122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    static base::Histogram* counter(NULL); \
123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!counter) \
124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      counter = base::CustomHistogram::FactoryGet(name, custom_ranges, \
125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                  base::Histogram::kNoFlags); \
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK_EQ(name, counter->histogram_name()); \
127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    counter->Add(sample); \
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } while (0)
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//------------------------------------------------------------------------------
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Define Debug vs non-debug flavors of macros.
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifndef NDEBUG
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define DHISTOGRAM_TIMES(name, sample) HISTOGRAM_TIMES(name, sample)
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define DHISTOGRAM_COUNTS(name, sample) HISTOGRAM_COUNTS(name, sample)
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define DHISTOGRAM_PERCENTAGE(name, under_one_hundred) HISTOGRAM_PERCENTAGE(\
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    name, under_one_hundred)
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define DHISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count)
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define DHISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) \
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count)
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define DHISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count)
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define DHISTOGRAM_ENUMERATION(name, sample, boundary_value) \
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    HISTOGRAM_ENUMERATION(name, sample, boundary_value)
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define DHISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges)
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else  // NDEBUG
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define DHISTOGRAM_TIMES(name, sample) do {} while (0)
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define DHISTOGRAM_COUNTS(name, sample) do {} while (0)
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define DHISTOGRAM_PERCENTAGE(name, under_one_hundred) do {} while (0)
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define DHISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    do {} while (0)
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define DHISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) \
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    do {} while (0)
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define DHISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    do {} while (0)
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define DHISTOGRAM_ENUMERATION(name, sample, boundary_value) do {} while (0)
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define DHISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    do {} while (0)
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif  // NDEBUG
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//------------------------------------------------------------------------------
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The following macros provide typical usage scenarios for callers that wish
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// to record histogram data, and have the data submitted/uploaded via UMA.
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Not all systems support such UMA, but if they do, the following macros
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// should work with the service.
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define UMA_HISTOGRAM_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    name, sample, base::TimeDelta::FromMilliseconds(1), \
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    base::TimeDelta::FromSeconds(10), 50)
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define UMA_HISTOGRAM_MEDIUM_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    name, sample, base::TimeDelta::FromMilliseconds(10), \
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    base::TimeDelta::FromMinutes(3), 50)
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use this macro when times can routinely be much longer than 10 seconds.
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define UMA_HISTOGRAM_LONG_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    name, sample, base::TimeDelta::FromMilliseconds(1), \
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    base::TimeDelta::FromHours(1), 50)
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \
187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    static base::Histogram* counter(NULL); \
188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!counter) \
189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \
190731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick            base::Histogram::kUmaTargetedHistogramFlag); \
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK_EQ(name, counter->histogram_name()); \
192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    counter->AddTime(sample); \
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } while (0)
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// DO NOT USE THIS.  It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES.
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define UMA_HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \
197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    static base::Histogram* counter(NULL); \
198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!counter) \
199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \
200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen           base::Histogram::kUmaTargetedHistogramFlag); \
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK_EQ(name, counter->histogram_name()); \
202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if ((sample) < (max)) counter->AddTime(sample); \
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } while (0)
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define UMA_HISTOGRAM_COUNTS(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    name, sample, 1, 1000000, 50)
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define UMA_HISTOGRAM_COUNTS_100(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    name, sample, 1, 100, 50)
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define UMA_HISTOGRAM_COUNTS_10000(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    name, sample, 1, 10000, 50)
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \
215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    static base::Histogram* counter(NULL); \
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!counter) \
217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      counter = base::Histogram::FactoryGet(name, min, max, bucket_count, \
218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          base::Histogram::kUmaTargetedHistogramFlag); \
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK_EQ(name, counter->histogram_name()); \
220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    counter->Add(sample); \
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } while (0)
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define UMA_HISTOGRAM_MEMORY_KB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    name, sample, 1000, 500000, 50)
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define UMA_HISTOGRAM_MEMORY_MB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    name, sample, 1, 1000, 50)
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define UMA_HISTOGRAM_PERCENTAGE(name, under_one_hundred) \
230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UMA_HISTOGRAM_ENUMERATION(name, under_one_hundred, 101)
231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#define UMA_HISTOGRAM_BOOLEAN(name, sample) do { \
233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    static base::Histogram* counter(NULL); \
234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!counter) \
235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      counter = base::BooleanHistogram::FactoryGet(name, \
236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          base::Histogram::kUmaTargetedHistogramFlag); \
237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DCHECK_EQ(name, counter->histogram_name()); \
238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    counter->AddBoolean(sample); \
239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } while (0)
240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define UMA_HISTOGRAM_ENUMERATION(name, sample, boundary_value) do { \
242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    static base::Histogram* counter(NULL); \
243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!counter) \
244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      counter = base::LinearHistogram::FactoryGet(name, 1, boundary_value, \
245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          boundary_value + 1, base::Histogram::kUmaTargetedHistogramFlag); \
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK_EQ(name, counter->histogram_name()); \
247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    counter->Add(sample); \
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } while (0)
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define UMA_HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) do { \
251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    static base::Histogram* counter(NULL); \
252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!counter) \
253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      counter = base::CustomHistogram::FactoryGet(name, custom_ranges, \
254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          base::Histogram::kUmaTargetedHistogramFlag); \
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK_EQ(name, counter->histogram_name()); \
256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    counter->Add(sample); \
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } while (0)
258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//------------------------------------------------------------------------------
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass BooleanHistogram;
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass CustomHistogram;
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass Histogram;
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass LinearHistogram;
265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass BASE_API Histogram {
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  typedef int Sample;  // Used for samples (and ranges of samples).
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  typedef int Count;  // Used to count samples in a bucket.
270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const Sample kSampleType_MAX = INT_MAX;
271dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Initialize maximum number of buckets in histograms as 16,384.
272dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  static const size_t kBucketCount_MAX;
273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  typedef std::vector<Count> Counts;
275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  typedef std::vector<Sample> Ranges;
276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
277513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // These enums are used to facilitate deserialization of renderer histograms
278513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // into the browser.
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  enum ClassType {
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    HISTOGRAM,
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LINEAR_HISTOGRAM,
282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    BOOLEAN_HISTOGRAM,
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CUSTOM_HISTOGRAM,
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NOT_VALID_IN_RENDERER
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  enum BucketLayout {
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPONENTIAL,
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LINEAR,
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CUSTOM
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  enum Flags {
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    kNoFlags = 0,
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    kUmaTargetedHistogramFlag = 0x1,  // Histogram should be UMA uploaded.
296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Indicate that the histogram was pickled to be sent across an IPC Channel.
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // If we observe this flag on a histogram being aggregated into after IPC,
299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // then we are running in a single process mode, and the aggregation should
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // not take place (as we would be aggregating back into the source
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // histogram!).
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    kIPCSerializationSourceFlag = 0x10,
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    kHexRangePrintingFlag = 0x8000,  // Fancy bucket-naming supported.
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
307513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  enum Inconsistencies {
308513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    NO_INCONSISTENCIES = 0x0,
309513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    RANGE_CHECKSUM_ERROR = 0x1,
310513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    BUCKET_ORDER_ERROR = 0x2,
311513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    COUNT_HIGH_ERROR = 0x4,
312513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    COUNT_LOW_ERROR = 0x8,
313513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
314513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    NEVER_EXCEEDED_VALUE = 0x10
315513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  };
316513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  struct DescriptionPair {
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Sample sample;
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const char* description;  // Null means end of a list of pairs.
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //----------------------------------------------------------------------------
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Statistic values, developed over the life of the histogram.
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  class BASE_API SampleSet {
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott   public:
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    explicit SampleSet();
3283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ~SampleSet();
3293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Adjust size of counts_ for use with given histogram.
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    void Resize(const Histogram& histogram);
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    void CheckSize(const Histogram& histogram) const;
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Accessor for histogram to make routine additions.
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    void Accumulate(Sample value, Count count, size_t index);
336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Accessor methods.
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Count counts(size_t i) const { return counts_[i]; }
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Count TotalCount() const;
340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int64 sum() const { return sum_; }
341513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    int64 redundant_count() const { return redundant_count_; }
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Arithmetic manipulation of corresponding elements of the set.
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    void Add(const SampleSet& other);
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    void Subtract(const SampleSet& other);
346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    bool Serialize(Pickle* pickle) const;
348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    bool Deserialize(void** iter, const Pickle& pickle);
349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott   protected:
351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Actual histogram data is stored in buckets, showing the count of values
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // that fit into each bucket.
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Counts counts_;
354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Save simple stats locally.  Note that this MIGHT get done in base class
356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // without shared memory at some point.
357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int64 sum_;         // sum of samples.
358513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
359513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch   private:
360513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // Allow tests to corrupt our innards for testing purposes.
361513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    FRIEND_TEST(HistogramTest, CorruptSampleCounts);
362513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
363513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // To help identify memory corruption, we reduntantly save the number of
364513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // samples we've accumulated into all of our buckets.  We can compare this
365513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // count to the sum of the counts in all buckets, and detect problems.  Note
366513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // that due to races in histogram accumulation (if a histogram is indeed
367513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // updated on several threads simultaneously), the tallies might mismatch,
368513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // and also the snapshotting code may asynchronously get a mismatch (though
369513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // generally either race based mismatch cause is VERY rare).
370513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    int64 redundant_count_;
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
372513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //----------------------------------------------------------------------------
374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // minimum should start from 1. 0 is invalid as a minimum. 0 is an implicit
375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // default underflow bucket.
376ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static Histogram* FactoryGet(const std::string& name,
377ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                               Sample minimum,
378ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                               Sample maximum,
379ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                               size_t bucket_count,
380ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                               Flags flags);
381ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static Histogram* FactoryTimeGet(const std::string& name,
382ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                   base::TimeDelta minimum,
383ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                   base::TimeDelta maximum,
384ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                   size_t bucket_count,
385ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                   Flags flags);
386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void Add(int value);
388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // This method is an interface, used only by BooleanHistogram.
3903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual void AddBoolean(bool value);
391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Accept a TimeDelta to increment.
393731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  void AddTime(TimeDelta time) {
394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Add(static_cast<int>(time.InMilliseconds()));
395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void AddSampleSet(const SampleSet& sample);
398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // This method is an interface, used only by LinearHistogram.
4003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual void SetRangeDescriptions(const DescriptionPair descriptions[]);
401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The following methods provide graphical histogram displays.
403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void WriteHTMLGraph(std::string* output) const;
404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void WriteAscii(bool graph_it, const std::string& newline,
405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                  std::string* output) const;
406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Support generic flagging of Histograms.
408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // 0x1 Currently used to mark this histogram to be recorded by UMA..
409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // 0x8000 means print ranges in hex.
410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void SetFlags(Flags flags) { flags_ = static_cast<Flags> (flags_ | flags); }
411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void ClearFlags(Flags flags) { flags_ = static_cast<Flags>(flags_ & ~flags); }
412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int flags() const { return flags_; }
413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Convenience methods for serializing/deserializing the histograms.
415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Histograms from Renderer process are serialized and sent to the browser.
416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Browser process reconstructs the histogram from the pickled version
417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // accumulates the browser-side shadow copy of histograms (that mirror
418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // histograms created in the renderer).
419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Serialize the given snapshot of a Histogram into a String. Uses
421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Pickle class to flatten the object.
422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static std::string SerializeHistogramInfo(const Histogram& histogram,
423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                            const SampleSet& snapshot);
424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The following method accepts a list of pickled histograms and
425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // builds a histogram and updates shadow copy of histogram data in the
426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // browser process.
427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static bool DeserializeHistogramInfo(const std::string& histogram_info);
428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
429513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Check to see if bucket ranges, counts and tallies in the snapshot are
430513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // consistent with the bucket ranges and checksums in our histogram.  This can
431513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // produce a false-alarm if a race occurred in the reading of the data during
432513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // a SnapShot process, but should otherwise be false at all times (unless we
433513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // have memory over-writes, or DRAM failures).
434513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  virtual Inconsistencies FindCorruption(const SampleSet& snapshot) const;
435513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //----------------------------------------------------------------------------
437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Accessors for factory constuction, serialization and testing.
438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //----------------------------------------------------------------------------
43921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  virtual ClassType histogram_type() const;
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const std::string& histogram_name() const { return histogram_name_; }
441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Sample declared_min() const { return declared_min_; }
442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Sample declared_max() const { return declared_max_; }
44321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  virtual Sample ranges(size_t i) const;
444dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  uint32 range_checksum() const { return range_checksum_; }
44521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  virtual size_t bucket_count() const;
446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Snapshot the current complete set of sample data.
447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Override with atomic/locked snapshot if needed.
448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void SnapshotSample(SampleSet* sample) const;
449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual bool HasConstructorArguments(Sample minimum, Sample maximum,
4513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       size_t bucket_count);
452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
453731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  virtual bool HasConstructorTimeDeltaArguments(TimeDelta minimum,
454731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                                TimeDelta maximum,
4553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                size_t bucket_count);
456dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Return true iff the range_checksum_ matches current ranges_ vector.
457dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  bool HasValidRangeChecksum() const;
458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott protected:
460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Histogram(const std::string& name, Sample minimum,
461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            Sample maximum, size_t bucket_count);
462731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  Histogram(const std::string& name, TimeDelta minimum,
463731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick            TimeDelta maximum, size_t bucket_count);
464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual ~Histogram();
466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
467dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Initialize ranges_ mapping.
468dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  void InitializeBucketRange();
469dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Method to override to skip the display of the i'th bucket if it's empty.
4713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual bool PrintEmptyBucket(size_t index) const;
472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //----------------------------------------------------------------------------
474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Methods to override to create histogram with different bucket widths.
475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //----------------------------------------------------------------------------
476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Find bucket to increment for sample value.
477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual size_t BucketIndex(Sample value) const;
478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Get normalized size, relative to the ranges_[i].
479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual double GetBucketSize(Count current, size_t i) const;
480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
481513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Recalculate range_checksum_.
482513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  void ResetRangeChecksum();
483513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Return a string description of what goes in a given bucket.
485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Most commonly this is the numeric value, but in derived classes it may
486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // be a name (or string description) given to the bucket.
487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual const std::string GetAsciiBucketRange(size_t it) const;
488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //----------------------------------------------------------------------------
490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Methods to override to create thread safe histogram.
491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //----------------------------------------------------------------------------
492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Update all our internal data, including histogram
493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void Accumulate(Sample value, Count count, size_t index);
494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //----------------------------------------------------------------------------
496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Accessors for derived classes.
497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //----------------------------------------------------------------------------
498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void SetBucketRange(size_t i, Sample value);
499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Validate that ranges_ was created sensibly (top and bottom range
501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // values relate properly to the declared_min_ and declared_max_)..
502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool ValidateBucketRanges() const;
503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
504dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  virtual uint32 CalculateRangeChecksum() const;
505dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
507513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Allow tests to corrupt our innards for testing purposes.
508513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  FRIEND_TEST(HistogramTest, CorruptBucketBounds);
509513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  FRIEND_TEST(HistogramTest, CorruptSampleCounts);
510dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  FRIEND_TEST(HistogramTest, Crc32SampleHash);
511dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  FRIEND_TEST(HistogramTest, Crc32TableTest);
512513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
513ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  friend class StatisticsRecorder;  // To allow it to delete duplicates.
514ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Post constructor initialization.
516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void Initialize();
517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
518dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Checksum function for accumulating range values into a checksum.
519dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  static uint32 Crc32(uint32 sum, Sample range);
520513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //----------------------------------------------------------------------------
522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Helpers for emitting Ascii graphic.  Each method appends data to output.
523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Find out how large the (graphically) the largest bucket will appear to be.
525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  double GetPeakBucketSize(const SampleSet& snapshot) const;
526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Write a common header message describing this histogram.
528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void WriteAsciiHeader(const SampleSet& snapshot,
529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        Count sample_count, std::string* output) const;
530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Write information about previous, current, and next buckets.
532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Information such as cumulative percentage, etc.
533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void WriteAsciiBucketContext(const int64 past, const Count current,
534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                               const int64 remaining, const size_t i,
535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                               std::string* output) const;
536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Write textual description of the bucket contents (relative to histogram).
538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Output is the count in the buckets, as well as the percentage.
539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void WriteAsciiBucketValue(Count current, double scaled_sum,
540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             std::string* output) const;
541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Produce actual graph (set of blank vs non blank char's) for a bucket.
543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void WriteAsciiBucketGraph(double current_size, double max_size,
544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             std::string* output) const;
545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //----------------------------------------------------------------------------
547dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Table for generating Crc32 values.
548dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  static const uint32 kCrcTable[256];
549dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  //----------------------------------------------------------------------------
550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Invariant values set at/near construction time
551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // ASCII version of original name given to the constructor.  All identically
553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // named instances will be coalesced cross-project.
554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const std::string histogram_name_;
555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Sample declared_min_;  // Less than this goes into counts_[0]
556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Sample declared_max_;  // Over this goes into counts_[bucket_count_ - 1].
557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t bucket_count_;  // Dimension of counts_[].
558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Flag the histogram for recording by UMA via metric_services.h.
560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Flags flags_;
561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // For each index, show the least value that can be stored in the
563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // corresponding bucket. We also append one extra element in this array,
564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // containing kSampleType_MAX, to make calculations easy.
565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The dimension of ranges_ is bucket_count + 1.
566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Ranges ranges_;
567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
568dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // For redundancy, we store a checksum of all the sample ranges when ranges
569dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // are generated.  If ever there is ever a difference, then the histogram must
570513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // have been corrupted.
571dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  uint32 range_checksum_;
572513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Finally, provide the state that changes with the addition of each new
574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // sample.
575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SampleSet sample_;
576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DISALLOW_COPY_AND_ASSIGN(Histogram);
578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//------------------------------------------------------------------------------
581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// LinearHistogram is a more traditional histogram, with evenly spaced
583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// buckets.
584ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass BASE_API LinearHistogram : public Histogram {
585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
5863f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  virtual ~LinearHistogram();
587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  /* minimum should start from 1. 0 is as minimum is invalid. 0 is an implicit
589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     default underflow bucket. */
590ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static Histogram* FactoryGet(const std::string& name,
591ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                               Sample minimum,
592ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                               Sample maximum,
593ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                               size_t bucket_count,
594ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                               Flags flags);
595ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static Histogram* FactoryTimeGet(const std::string& name,
596ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                   TimeDelta minimum,
597ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                   TimeDelta maximum,
598ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                   size_t bucket_count,
599ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                   Flags flags);
600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
6013f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // Overridden from Histogram:
6023f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  virtual ClassType histogram_type() const;
6033f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
6043f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // Store a list of number/text values for use in rendering the histogram.
6053f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // The last element in the array has a null in its "description" slot.
6063f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  virtual void SetRangeDescriptions(const DescriptionPair descriptions[]);
6073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott protected:
609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LinearHistogram(const std::string& name, Sample minimum,
610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                  Sample maximum, size_t bucket_count);
611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
612731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  LinearHistogram(const std::string& name, TimeDelta minimum,
613731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                  TimeDelta maximum, size_t bucket_count);
614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Initialize ranges_ mapping.
616dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  void InitializeBucketRange();
617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual double GetBucketSize(Count current, size_t i) const;
618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If we have a description for a bucket, then return that.  Otherwise
620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // let parent class provide a (numeric) description.
621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual const std::string GetAsciiBucketRange(size_t i) const;
622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Skip printing of name for numeric range if we have a name (and if this is
624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // an empty bucket).
625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual bool PrintEmptyBucket(size_t index) const;
626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // For some ranges, we store a printable description of a bucket range.
629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If there is no desciption, then GetAsciiBucketRange() uses parent class
630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // to provide a description.
631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  typedef std::map<Sample, std::string> BucketDescriptionMap;
632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  BucketDescriptionMap bucket_description_;
633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DISALLOW_COPY_AND_ASSIGN(LinearHistogram);
635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//------------------------------------------------------------------------------
638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// BooleanHistogram is a histogram for booleans.
640ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass BASE_API BooleanHistogram : public LinearHistogram {
641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
642ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static Histogram* FactoryGet(const std::string& name, Flags flags);
643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
6443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual ClassType histogram_type() const;
645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
6463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual void AddBoolean(bool value);
647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
6493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  explicit BooleanHistogram(const std::string& name);
650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DISALLOW_COPY_AND_ASSIGN(BooleanHistogram);
652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//------------------------------------------------------------------------------
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// CustomHistogram is a histogram for a set of custom integers.
657ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass BASE_API CustomHistogram : public Histogram {
658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
660ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static Histogram* FactoryGet(const std::string& name,
661ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                               const std::vector<Sample>& custom_ranges,
662ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                               Flags flags);
663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
6643f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // Overridden from Histogram:
6653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  virtual ClassType histogram_type() const;
6663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected:
668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CustomHistogram(const std::string& name,
669513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                  const std::vector<Sample>& custom_ranges);
670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Initialize ranges_ mapping.
672dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  void InitializedCustomBucketRange(const std::vector<Sample>& custom_ranges);
673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual double GetBucketSize(Count current, size_t i) const;
674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(CustomHistogram);
676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------
679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// StatisticsRecorder handles all histograms in the system.  It provides a
680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// general place for histograms to register, and supports a global API for
681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// accessing (i.e., dumping, or graphing) the data in all the histograms.
682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
683ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass BASE_API StatisticsRecorder {
684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
685ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  typedef std::vector<Histogram*> Histograms;
686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  StatisticsRecorder();
688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ~StatisticsRecorder();
690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Find out if histograms can now be registered into our list.
69221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  static bool IsActive();
693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
694dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Register, or add a new histogram to the collection of statistics. If an
695dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // identically named histogram is already registered, then the argument
696ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // |histogram| will deleted.  The returned value is always the registered
697ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // histogram (either the argument, or the pre-existing registered histogram).
698ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static Histogram* RegisterOrDeleteDuplicate(Histogram* histogram);
699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Methods for printing histograms.  Only histograms which have query as
701c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // a substring are written to output (an empty string will process all
702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // registered histograms).
703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static void WriteHTMLGraph(const std::string& query, std::string* output);
704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static void WriteGraph(const std::string& query, std::string* output);
705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
706c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Method for extracting histograms which were marked for use by UMA.
707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static void GetHistograms(Histograms* output);
708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Find a histogram by name. It matches the exact name. This method is thread
710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // safe.  If a matching histogram is not found, then the |histogram| is
711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // not changed.
712ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static bool FindHistogram(const std::string& query, Histogram** histogram);
713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static bool dump_on_exit() { return dump_on_exit_; }
715c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static void set_dump_on_exit(bool enable) { dump_on_exit_ = enable; }
717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // GetSnapshot copies some of the pointers to registered histograms into the
719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // caller supplied vector (Histograms).  Only histograms with names matching
720c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // query are returned. The query must be a substring of histogram name for its
721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // pointer to be copied.
722c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static void GetSnapshot(const std::string& query, Histograms* snapshot);
723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We keep all registered histograms in a map, from name to histogram.
727ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  typedef std::map<std::string, Histogram*> HistogramMap;
728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
729c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static HistogramMap* histograms_;
730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
731c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // lock protects access to the above map.
7323f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  static base::Lock* lock_;
733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
734c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Dump all known histograms to log.
735c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static bool dump_on_exit_;
736c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder);
738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
740731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}  // namespace base
741731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
742731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#endif  // BASE_METRICS_HISTOGRAM_H_
743