Output data about media requests to the netlog too.
[chromium-blink-merge.git] / base / histogram.h
blob1d135443795bc941d3d870ce30566b68ccd99a24
1 // Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // 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).
9 // It supports calls to accumulate either time intervals (which are processed
10 // as integral number of milliseconds), or arbitrary integral units.
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.
31 #ifndef BASE_HISTOGRAM_H_
32 #define BASE_HISTOGRAM_H_
33 #pragma once
35 #include <map>
36 #include <string>
37 #include <vector>
39 #include "base/ref_counted.h"
40 #include "base/logging.h"
41 #include "base/time.h"
43 class Lock;
45 //------------------------------------------------------------------------------
46 // Provide easy general purpose histogram in a macro, just like stats counters.
47 // The first four macros use 50 buckets.
49 #define HISTOGRAM_TIMES(name, sample) HISTOGRAM_CUSTOM_TIMES( \
50 name, sample, base::TimeDelta::FromMilliseconds(1), \
51 base::TimeDelta::FromSeconds(10), 50)
53 #define HISTOGRAM_COUNTS(name, sample) HISTOGRAM_CUSTOM_COUNTS( \
54 name, sample, 1, 1000000, 50)
56 #define HISTOGRAM_COUNTS_100(name, sample) HISTOGRAM_CUSTOM_COUNTS( \
57 name, sample, 1, 100, 50)
59 #define HISTOGRAM_COUNTS_10000(name, sample) HISTOGRAM_CUSTOM_COUNTS( \
60 name, sample, 1, 10000, 50)
62 #define HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \
63 static scoped_refptr<Histogram> counter = Histogram::FactoryGet( \
64 name, min, max, bucket_count, Histogram::kNoFlags); \
65 DCHECK_EQ(name, counter->histogram_name()); \
66 if (counter.get()) counter->Add(sample); \
67 } while (0)
69 #define HISTOGRAM_PERCENTAGE(name, under_one_hundred) \
70 HISTOGRAM_ENUMERATION(name, under_one_hundred, 101)
72 // For folks that need real specific times, use this to select a precise range
73 // of times you want plotted, and the number of buckets you want used.
74 #define HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \
75 static scoped_refptr<Histogram> counter = Histogram::FactoryTimeGet( \
76 name, min, max, bucket_count, Histogram::kNoFlags); \
77 DCHECK_EQ(name, counter->histogram_name()); \
78 if (counter.get()) counter->AddTime(sample); \
79 } while (0)
81 // DO NOT USE THIS. It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES.
82 #define HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \
83 static scoped_refptr<Histogram> counter = Histogram::FactoryTimeGet( \
84 name, min, max, bucket_count, Histogram::kNoFlags); \
85 DCHECK_EQ(name, counter->histogram_name()); \
86 if ((sample) < (max) && counter.get()) counter->AddTime(sample); \
87 } while (0)
89 // Support histograming of an enumerated value. The samples should always be
90 // less than boundary_value.
92 #define HISTOGRAM_ENUMERATION(name, sample, boundary_value) do { \
93 static scoped_refptr<Histogram> counter = LinearHistogram::FactoryGet( \
94 name, 1, boundary_value, boundary_value + 1, Histogram::kNoFlags); \
95 DCHECK_EQ(name, counter->histogram_name()); \
96 if (counter.get()) counter->Add(sample); \
97 } while (0)
99 #define HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) do { \
100 static scoped_refptr<Histogram> counter = CustomHistogram::FactoryGet( \
101 name, custom_ranges, Histogram::kNoFlags); \
102 DCHECK_EQ(name, counter->histogram_name()); \
103 if (counter.get()) counter->Add(sample); \
104 } while (0)
107 //------------------------------------------------------------------------------
108 // Define Debug vs non-debug flavors of macros.
109 #ifndef NDEBUG
111 #define DHISTOGRAM_TIMES(name, sample) HISTOGRAM_TIMES(name, sample)
112 #define DHISTOGRAM_COUNTS(name, sample) HISTOGRAM_COUNTS(name, sample)
113 #define DHISTOGRAM_PERCENTAGE(name, under_one_hundred) HISTOGRAM_PERCENTAGE(\
114 name, under_one_hundred)
115 #define DHISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \
116 HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count)
117 #define DHISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) \
118 HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count)
119 #define DHISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \
120 HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count)
121 #define DHISTOGRAM_ENUMERATION(name, sample, boundary_value) \
122 HISTOGRAM_ENUMERATION(name, sample, boundary_value)
123 #define DHISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \
124 HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges)
126 #else // NDEBUG
128 #define DHISTOGRAM_TIMES(name, sample) do {} while (0)
129 #define DHISTOGRAM_COUNTS(name, sample) do {} while (0)
130 #define DHISTOGRAM_PERCENTAGE(name, under_one_hundred) do {} while (0)
131 #define DHISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \
132 do {} while (0)
133 #define DHISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) \
134 do {} while (0)
135 #define DHISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \
136 do {} while (0)
137 #define DHISTOGRAM_ENUMERATION(name, sample, boundary_value) do {} while (0)
138 #define DHISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \
139 do {} while (0)
141 #endif // NDEBUG
143 //------------------------------------------------------------------------------
144 // The following macros provide typical usage scenarios for callers that wish
145 // to record histogram data, and have the data submitted/uploaded via UMA.
146 // Not all systems support such UMA, but if they do, the following macros
147 // should work with the service.
149 #define UMA_HISTOGRAM_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \
150 name, sample, base::TimeDelta::FromMilliseconds(1), \
151 base::TimeDelta::FromSeconds(10), 50)
153 #define UMA_HISTOGRAM_MEDIUM_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \
154 name, sample, base::TimeDelta::FromMilliseconds(10), \
155 base::TimeDelta::FromMinutes(3), 50)
157 // Use this macro when times can routinely be much longer than 10 seconds.
158 #define UMA_HISTOGRAM_LONG_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \
159 name, sample, base::TimeDelta::FromMilliseconds(1), \
160 base::TimeDelta::FromHours(1), 50)
162 #define UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \
163 static scoped_refptr<Histogram> counter = Histogram::FactoryTimeGet( \
164 name, min, max, bucket_count, Histogram::kUmaTargetedHistogramFlag); \
165 DCHECK_EQ(name, counter->histogram_name()); \
166 if (counter.get()) counter->AddTime(sample); \
167 } while (0)
169 // DO NOT USE THIS. It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES.
170 #define UMA_HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \
171 static scoped_refptr<Histogram> counter = Histogram::FactoryTimeGet( \
172 name, min, max, bucket_count, Histogram::kUmaTargetedHistogramFlag); \
173 DCHECK_EQ(name, counter->histogram_name()); \
174 if ((sample) < (max) && counter.get()) counter->AddTime(sample); \
175 } while (0)
177 #define UMA_HISTOGRAM_COUNTS(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
178 name, sample, 1, 1000000, 50)
180 #define UMA_HISTOGRAM_COUNTS_100(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
181 name, sample, 1, 100, 50)
183 #define UMA_HISTOGRAM_COUNTS_10000(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
184 name, sample, 1, 10000, 50)
186 #define UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \
187 static scoped_refptr<Histogram> counter = Histogram::FactoryGet( \
188 name, min, max, bucket_count, Histogram::kUmaTargetedHistogramFlag); \
189 DCHECK_EQ(name, counter->histogram_name()); \
190 if (counter.get()) counter->Add(sample); \
191 } while (0)
193 #define UMA_HISTOGRAM_MEMORY_KB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
194 name, sample, 1000, 500000, 50)
196 #define UMA_HISTOGRAM_MEMORY_MB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
197 name, sample, 1, 1000, 50)
199 #define UMA_HISTOGRAM_PERCENTAGE(name, under_one_hundred) \
200 UMA_HISTOGRAM_ENUMERATION(name, under_one_hundred, 101)
202 #define UMA_HISTOGRAM_ENUMERATION(name, sample, boundary_value) do { \
203 static scoped_refptr<Histogram> counter = LinearHistogram::FactoryGet( \
204 name, 1, boundary_value, boundary_value + 1, \
205 Histogram::kUmaTargetedHistogramFlag); \
206 DCHECK_EQ(name, counter->histogram_name()); \
207 if (counter.get()) counter->Add(sample); \
208 } while (0)
210 #define UMA_HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) do { \
211 static scoped_refptr<Histogram> counter = CustomHistogram::FactoryGet( \
212 name, custom_ranges, Histogram::kUmaTargetedHistogramFlag); \
213 DCHECK_EQ(name, counter->histogram_name()); \
214 if (counter.get()) counter->Add(sample); \
215 } while (0)
217 //------------------------------------------------------------------------------
219 class BooleanHistogram;
220 class CustomHistogram;
221 class Histogram;
222 class LinearHistogram;
223 class Pickle;
225 namespace disk_cache {
226 class StatsHistogram;
227 }; // namespace disk_cache
230 class Histogram : public base::RefCountedThreadSafe<Histogram> {
231 public:
232 typedef int Sample; // Used for samples (and ranges of samples).
233 typedef int Count; // Used to count samples in a bucket.
234 static const Sample kSampleType_MAX = INT_MAX;
236 typedef std::vector<Count> Counts;
237 typedef std::vector<Sample> Ranges;
239 /* These enums are meant to facilitate deserialization of renderer histograms
240 into the browser. */
241 enum ClassType {
242 HISTOGRAM,
243 LINEAR_HISTOGRAM,
244 BOOLEAN_HISTOGRAM,
245 CUSTOM_HISTOGRAM,
246 NOT_VALID_IN_RENDERER
249 enum BucketLayout {
250 EXPONENTIAL,
251 LINEAR,
252 CUSTOM
255 enum Flags {
256 kNoFlags = 0,
257 kUmaTargetedHistogramFlag = 0x1, // Histogram should be UMA uploaded.
259 // Indicate that the histogram was pickled to be sent across an IPC Channel.
260 // If we observe this flag on a histogram being aggregated into after IPC,
261 // then we are running in a single process mode, and the aggregation should
262 // not take place (as we would be aggregating back into the source
263 // histogram!).
264 kIPCSerializationSourceFlag = 0x10,
266 kHexRangePrintingFlag = 0x8000, // Fancy bucket-naming supported.
269 struct DescriptionPair {
270 Sample sample;
271 const char* description; // Null means end of a list of pairs.
274 //----------------------------------------------------------------------------
275 // Statistic values, developed over the life of the histogram.
277 class SampleSet {
278 public:
279 explicit SampleSet();
280 // Adjust size of counts_ for use with given histogram.
281 void Resize(const Histogram& histogram);
282 void CheckSize(const Histogram& histogram) const;
284 // Accessor for histogram to make routine additions.
285 void Accumulate(Sample value, Count count, size_t index);
287 // Accessor methods.
288 Count counts(size_t i) const { return counts_[i]; }
289 Count TotalCount() const;
290 int64 sum() const { return sum_; }
291 int64 square_sum() const { return square_sum_; }
293 // Arithmetic manipulation of corresponding elements of the set.
294 void Add(const SampleSet& other);
295 void Subtract(const SampleSet& other);
297 bool Serialize(Pickle* pickle) const;
298 bool Deserialize(void** iter, const Pickle& pickle);
300 protected:
301 // Actual histogram data is stored in buckets, showing the count of values
302 // that fit into each bucket.
303 Counts counts_;
305 // Save simple stats locally. Note that this MIGHT get done in base class
306 // without shared memory at some point.
307 int64 sum_; // sum of samples.
308 int64 square_sum_; // sum of squares of samples.
310 //----------------------------------------------------------------------------
311 // minimum should start from 1. 0 is invalid as a minimum. 0 is an implicit
312 // default underflow bucket.
313 static scoped_refptr<Histogram> FactoryGet(const std::string& name,
314 Sample minimum, Sample maximum, size_t bucket_count, Flags flags);
315 static scoped_refptr<Histogram> FactoryTimeGet(const std::string& name,
316 base::TimeDelta minimum, base::TimeDelta maximum, size_t bucket_count,
317 Flags flags);
319 void Add(int value);
321 // This method is an interface, used only by BooleanHistogram.
322 virtual void AddBoolean(bool value);
324 // Accept a TimeDelta to increment.
325 void AddTime(base::TimeDelta time) {
326 Add(static_cast<int>(time.InMilliseconds()));
329 void AddSampleSet(const SampleSet& sample);
331 // This method is an interface, used only by LinearHistogram.
332 virtual void SetRangeDescriptions(const DescriptionPair descriptions[]);
334 // The following methods provide graphical histogram displays.
335 void WriteHTMLGraph(std::string* output) const;
336 void WriteAscii(bool graph_it, const std::string& newline,
337 std::string* output) const;
339 // Support generic flagging of Histograms.
340 // 0x1 Currently used to mark this histogram to be recorded by UMA..
341 // 0x8000 means print ranges in hex.
342 void SetFlags(Flags flags) { flags_ = static_cast<Flags> (flags_ | flags); }
343 void ClearFlags(Flags flags) { flags_ = static_cast<Flags>(flags_ & ~flags); }
344 int flags() const { return flags_; }
346 // Convenience methods for serializing/deserializing the histograms.
347 // Histograms from Renderer process are serialized and sent to the browser.
348 // Browser process reconstructs the histogram from the pickled version
349 // accumulates the browser-side shadow copy of histograms (that mirror
350 // histograms created in the renderer).
352 // Serialize the given snapshot of a Histogram into a String. Uses
353 // Pickle class to flatten the object.
354 static std::string SerializeHistogramInfo(const Histogram& histogram,
355 const SampleSet& snapshot);
356 // The following method accepts a list of pickled histograms and
357 // builds a histogram and updates shadow copy of histogram data in the
358 // browser process.
359 static bool DeserializeHistogramInfo(const std::string& histogram_info);
361 //----------------------------------------------------------------------------
362 // Accessors for factory constuction, serialization and testing.
363 //----------------------------------------------------------------------------
364 virtual ClassType histogram_type() const { return HISTOGRAM; }
365 const std::string& histogram_name() const { return histogram_name_; }
366 Sample declared_min() const { return declared_min_; }
367 Sample declared_max() const { return declared_max_; }
368 virtual Sample ranges(size_t i) const { return ranges_[i];}
369 virtual size_t bucket_count() const { return bucket_count_; }
370 // Snapshot the current complete set of sample data.
371 // Override with atomic/locked snapshot if needed.
372 virtual void SnapshotSample(SampleSet* sample) const;
374 virtual bool HasConstructorArguments(Sample minimum, Sample maximum,
375 size_t bucket_count);
377 virtual bool HasConstructorTimeDeltaArguments(base::TimeDelta minimum,
378 base::TimeDelta maximum,
379 size_t bucket_count);
381 protected:
382 friend class base::RefCountedThreadSafe<Histogram>;
383 Histogram(const std::string& name, Sample minimum,
384 Sample maximum, size_t bucket_count);
385 Histogram(const std::string& name, base::TimeDelta minimum,
386 base::TimeDelta maximum, size_t bucket_count);
388 virtual ~Histogram();
390 // Method to override to skip the display of the i'th bucket if it's empty.
391 virtual bool PrintEmptyBucket(size_t index) const;
393 //----------------------------------------------------------------------------
394 // Methods to override to create histogram with different bucket widths.
395 //----------------------------------------------------------------------------
396 // Initialize ranges_ mapping.
397 virtual void InitializeBucketRange();
398 // Find bucket to increment for sample value.
399 virtual size_t BucketIndex(Sample value) const;
400 // Get normalized size, relative to the ranges_[i].
401 virtual double GetBucketSize(Count current, size_t i) const;
403 // Return a string description of what goes in a given bucket.
404 // Most commonly this is the numeric value, but in derived classes it may
405 // be a name (or string description) given to the bucket.
406 virtual const std::string GetAsciiBucketRange(size_t it) const;
408 //----------------------------------------------------------------------------
409 // Methods to override to create thread safe histogram.
410 //----------------------------------------------------------------------------
411 // Update all our internal data, including histogram
412 virtual void Accumulate(Sample value, Count count, size_t index);
414 //----------------------------------------------------------------------------
415 // Accessors for derived classes.
416 //----------------------------------------------------------------------------
417 void SetBucketRange(size_t i, Sample value);
419 // Validate that ranges_ was created sensibly (top and bottom range
420 // values relate properly to the declared_min_ and declared_max_)..
421 bool ValidateBucketRanges() const;
423 private:
424 // Post constructor initialization.
425 void Initialize();
427 //----------------------------------------------------------------------------
428 // Helpers for emitting Ascii graphic. Each method appends data to output.
430 // Find out how large the (graphically) the largest bucket will appear to be.
431 double GetPeakBucketSize(const SampleSet& snapshot) const;
433 // Write a common header message describing this histogram.
434 void WriteAsciiHeader(const SampleSet& snapshot,
435 Count sample_count, std::string* output) const;
437 // Write information about previous, current, and next buckets.
438 // Information such as cumulative percentage, etc.
439 void WriteAsciiBucketContext(const int64 past, const Count current,
440 const int64 remaining, const size_t i,
441 std::string* output) const;
443 // Write textual description of the bucket contents (relative to histogram).
444 // Output is the count in the buckets, as well as the percentage.
445 void WriteAsciiBucketValue(Count current, double scaled_sum,
446 std::string* output) const;
448 // Produce actual graph (set of blank vs non blank char's) for a bucket.
449 void WriteAsciiBucketGraph(double current_size, double max_size,
450 std::string* output) const;
452 //----------------------------------------------------------------------------
453 // Invariant values set at/near construction time
455 // ASCII version of original name given to the constructor. All identically
456 // named instances will be coalesced cross-project.
457 const std::string histogram_name_;
458 Sample declared_min_; // Less than this goes into counts_[0]
459 Sample declared_max_; // Over this goes into counts_[bucket_count_ - 1].
460 size_t bucket_count_; // Dimension of counts_[].
462 // Flag the histogram for recording by UMA via metric_services.h.
463 Flags flags_;
465 // For each index, show the least value that can be stored in the
466 // corresponding bucket. We also append one extra element in this array,
467 // containing kSampleType_MAX, to make calculations easy.
468 // The dimension of ranges_ is bucket_count + 1.
469 Ranges ranges_;
471 // Finally, provide the state that changes with the addition of each new
472 // sample.
473 SampleSet sample_;
475 DISALLOW_COPY_AND_ASSIGN(Histogram);
478 //------------------------------------------------------------------------------
480 // LinearHistogram is a more traditional histogram, with evenly spaced
481 // buckets.
482 class LinearHistogram : public Histogram {
483 public:
484 virtual ClassType histogram_type() const;
486 // Store a list of number/text values for use in rendering the histogram.
487 // The last element in the array has a null in its "description" slot.
488 virtual void SetRangeDescriptions(const DescriptionPair descriptions[]);
490 /* minimum should start from 1. 0 is as minimum is invalid. 0 is an implicit
491 default underflow bucket. */
492 static scoped_refptr<Histogram> FactoryGet(const std::string& name,
493 Sample minimum, Sample maximum, size_t bucket_count, Flags flags);
494 static scoped_refptr<Histogram> FactoryTimeGet(const std::string& name,
495 base::TimeDelta minimum, base::TimeDelta maximum, size_t bucket_count,
496 Flags flags);
498 protected:
499 LinearHistogram(const std::string& name, Sample minimum,
500 Sample maximum, size_t bucket_count);
502 LinearHistogram(const std::string& name, base::TimeDelta minimum,
503 base::TimeDelta maximum, size_t bucket_count);
505 // Initialize ranges_ mapping.
506 virtual void InitializeBucketRange();
507 virtual double GetBucketSize(Count current, size_t i) const;
509 // If we have a description for a bucket, then return that. Otherwise
510 // let parent class provide a (numeric) description.
511 virtual const std::string GetAsciiBucketRange(size_t i) const;
513 // Skip printing of name for numeric range if we have a name (and if this is
514 // an empty bucket).
515 virtual bool PrintEmptyBucket(size_t index) const;
517 private:
518 // For some ranges, we store a printable description of a bucket range.
519 // If there is no desciption, then GetAsciiBucketRange() uses parent class
520 // to provide a description.
521 typedef std::map<Sample, std::string> BucketDescriptionMap;
522 BucketDescriptionMap bucket_description_;
524 DISALLOW_COPY_AND_ASSIGN(LinearHistogram);
527 //------------------------------------------------------------------------------
529 // BooleanHistogram is a histogram for booleans.
530 class BooleanHistogram : public LinearHistogram {
531 public:
532 static scoped_refptr<Histogram> FactoryGet(const std::string& name,
533 Flags flags);
535 virtual ClassType histogram_type() const;
537 virtual void AddBoolean(bool value);
539 private:
540 explicit BooleanHistogram(const std::string& name);
542 DISALLOW_COPY_AND_ASSIGN(BooleanHistogram);
545 //------------------------------------------------------------------------------
547 // CustomHistogram is a histogram for a set of custom integers.
548 class CustomHistogram : public Histogram {
549 public:
550 virtual ClassType histogram_type() const;
552 static scoped_refptr<Histogram> FactoryGet(const std::string& name,
553 const std::vector<int>& custom_ranges, Flags flags);
555 protected:
556 CustomHistogram(const std::string& name,
557 const std::vector<int>& custom_ranges);
559 // Initialize ranges_ mapping.
560 virtual void InitializeBucketRange();
561 virtual double GetBucketSize(Count current, size_t i) const;
563 private:
564 // Temporary pointer used during construction/initialization, and then NULLed.
565 const std::vector<int>* ranges_vector_;
567 DISALLOW_COPY_AND_ASSIGN(CustomHistogram);
570 //------------------------------------------------------------------------------
571 // StatisticsRecorder handles all histograms in the system. It provides a
572 // general place for histograms to register, and supports a global API for
573 // accessing (i.e., dumping, or graphing) the data in all the histograms.
575 class StatisticsRecorder {
576 public:
577 typedef std::vector<scoped_refptr<Histogram> > Histograms;
579 StatisticsRecorder();
581 ~StatisticsRecorder();
583 // Find out if histograms can now be registered into our list.
584 static bool WasStarted();
586 // Register, or add a new histogram to the collection of statistics.
587 static void Register(Histogram* histogram);
589 // Methods for printing histograms. Only histograms which have query as
590 // a substring are written to output (an empty string will process all
591 // registered histograms).
592 static void WriteHTMLGraph(const std::string& query, std::string* output);
593 static void WriteGraph(const std::string& query, std::string* output);
595 // Method for extracting histograms which were marked for use by UMA.
596 static void GetHistograms(Histograms* output);
598 // Find a histogram by name. It matches the exact name. This method is thread
599 // safe. If a matching histogram is not found, then the |histogram| is
600 // not changed.
601 static bool FindHistogram(const std::string& query,
602 scoped_refptr<Histogram>* histogram);
604 static bool dump_on_exit() { return dump_on_exit_; }
606 static void set_dump_on_exit(bool enable) { dump_on_exit_ = enable; }
608 // GetSnapshot copies some of the pointers to registered histograms into the
609 // caller supplied vector (Histograms). Only histograms with names matching
610 // query are returned. The query must be a substring of histogram name for its
611 // pointer to be copied.
612 static void GetSnapshot(const std::string& query, Histograms* snapshot);
615 private:
616 // We keep all registered histograms in a map, from name to histogram.
617 typedef std::map<std::string, scoped_refptr<Histogram> > HistogramMap;
619 static HistogramMap* histograms_;
621 // lock protects access to the above map.
622 static Lock* lock_;
624 // Dump all known histograms to log.
625 static bool dump_on_exit_;
627 DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder);
630 #endif // BASE_HISTOGRAM_H_