• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Histogram is an object that aggregates statistics, and can summarize them in
6 // various forms, including ASCII graphical, HTML, and numerically (as a
7 // vector of numbers corresponding to each of the aggregating buckets).
8 
9 // It supports calls to accumulate either time intervals (which are processed
10 // as integral number of milliseconds), or arbitrary integral units.
11 
12 // For Histogram (exponential histogram), LinearHistogram and CustomHistogram,
13 // the minimum for a declared range is 1 (instead of 0), while the maximum is
14 // (HistogramBase::kSampleType_MAX - 1). However, there will always be underflow
15 // and overflow buckets added automatically, so a 0 bucket will always exist
16 // even when a minimum value of 1 is specified.
17 
18 // Each use of a histogram with the same name will reference the same underlying
19 // data, so it is safe to record to the same histogram from multiple locations
20 // in the code. It is a runtime error if all uses of the same histogram do not
21 // agree exactly in type, bucket size and range.
22 
23 // For Histogram and LinearHistogram, the maximum for a declared range should
24 // always be larger (not equal) than minimal range. Zero and
25 // HistogramBase::kSampleType_MAX are implicitly added as first and last ranges,
26 // so the smallest legal bucket_count is 3. However CustomHistogram can have
27 // bucket count as 2 (when you give a custom ranges vector containing only 1
28 // range).
29 // For these 3 kinds of histograms, the max bucket count is always
30 // (Histogram::kBucketCount_MAX - 1).
31 
32 // The buckets layout of class Histogram is exponential. For example, buckets
33 // might contain (sequentially) the count of values in the following intervals:
34 // [0,1), [1,2), [2,4), [4,8), [8,16), [16,32), [32,64), [64,infinity)
35 // That bucket allocation would actually result from construction of a histogram
36 // for values between 1 and 64, with 8 buckets, such as:
37 // Histogram count("some name", 1, 64, 8);
38 // Note that the underflow bucket [0,1) and the overflow bucket [64,infinity)
39 // are also counted by the constructor in the user supplied "bucket_count"
40 // argument.
41 // The above example has an exponential ratio of 2 (doubling the bucket width
42 // in each consecutive bucket).  The Histogram class automatically calculates
43 // the smallest ratio that it can use to construct the number of buckets
44 // selected in the constructor.  An another example, if you had 50 buckets,
45 // and millisecond time values from 1 to 10000, then the ratio between
46 // consecutive bucket widths will be approximately somewhere around the 50th
47 // root of 10000.  This approach provides very fine grain (narrow) buckets
48 // at the low end of the histogram scale, but allows the histogram to cover a
49 // gigantic range with the addition of very few buckets.
50 
51 // Usually we use macros to define and use a histogram, which are defined in
52 // base/metrics/histogram_macros.h. Note: Callers should include that header
53 // directly if they only access the histogram APIs through macros.
54 //
55 // Macros use a pattern involving a function static variable, that is a pointer
56 // to a histogram.  This static is explicitly initialized on any thread
57 // that detects a uninitialized (NULL) pointer.  The potentially racy
58 // initialization is not a problem as it is always set to point to the same
59 // value (i.e., the FactoryGet always returns the same value).  FactoryGet
60 // is also completely thread safe, which results in a completely thread safe,
61 // and relatively fast, set of counters.  To avoid races at shutdown, the static
62 // pointer is NOT deleted, and we leak the histograms at process termination.
63 
64 #ifndef BASE_METRICS_HISTOGRAM_H_
65 #define BASE_METRICS_HISTOGRAM_H_
66 
67 #include <stddef.h>
68 #include <stdint.h>
69 
70 #include <map>
71 #include <memory>
72 #include <string>
73 #include <string_view>
74 #include <vector>
75 
76 #include "base/base_export.h"
77 #include "base/compiler_specific.h"
78 #include "base/containers/span.h"
79 #include "base/dcheck_is_on.h"
80 #include "base/gtest_prod_util.h"
81 #include "base/memory/raw_ptr.h"
82 #include "base/metrics/bucket_ranges.h"
83 #include "base/metrics/histogram_base.h"
84 #include "base/metrics/histogram_samples.h"
85 #include "base/time/time.h"
86 #include "base/values.h"
87 
88 namespace base {
89 
90 class BooleanHistogram;
91 class CustomHistogram;
92 class DelayedPersistentAllocation;
93 class Histogram;
94 class HistogramTest;
95 class LinearHistogram;
96 class Pickle;
97 class PickleIterator;
98 class SampleVector;
99 class SampleVectorBase;
100 
101 class BASE_EXPORT Histogram : public HistogramBase {
102  public:
103   // Initialize maximum number of buckets in histograms as 1000, plus over and
104   // under.  This must be a value that fits in a uint32_t (since that's how we
105   // serialize bucket counts) as well as a Sample (since samples can be up to
106   // this value).
107   static constexpr size_t kBucketCount_MAX = 1002;
108 
109   typedef std::vector<Count> Counts;
110 
111   Histogram(const Histogram&) = delete;
112   Histogram& operator=(const Histogram&) = delete;
113 
114   ~Histogram() override;
115 
116   //----------------------------------------------------------------------------
117   // For a valid histogram, input should follow these restrictions:
118   // minimum > 0 (if a minimum below 1 is specified, it will implicitly be
119   //              normalized up to 1)
120   // maximum > minimum
121   // buckets > 2 [minimum buckets needed: underflow, overflow and the range]
122   // Additionally,
123   // buckets <= (maximum - minimum + 2) - this is to ensure that we don't have
124   // more buckets than the range of numbers; having more buckets than 1 per
125   // value in the range would be nonsensical.
126   static HistogramBase* FactoryGet(std::string_view name,
127                                    Sample minimum,
128                                    Sample maximum,
129                                    size_t bucket_count,
130                                    int32_t flags);
131   static HistogramBase* FactoryTimeGet(std::string_view name,
132                                        base::TimeDelta minimum,
133                                        base::TimeDelta maximum,
134                                        size_t bucket_count,
135                                        int32_t flags);
136   static HistogramBase* FactoryMicrosecondsTimeGet(std::string_view name,
137                                                    base::TimeDelta minimum,
138                                                    base::TimeDelta maximum,
139                                                    size_t bucket_count,
140                                                    int32_t flags);
141 
142   // Overloads of the above functions that take a const std::string& or const
143   // char* |name| param, to avoid code bloat from the std::string constructor
144   // being inlined into call sites.
145   static HistogramBase* FactoryGet(const std::string& name,
146                                    Sample minimum,
147                                    Sample maximum,
148                                    size_t bucket_count,
149                                    int32_t flags);
150   static HistogramBase* FactoryTimeGet(const std::string& name,
151                                        base::TimeDelta minimum,
152                                        base::TimeDelta maximum,
153                                        size_t bucket_count,
154                                        int32_t flags);
155   static HistogramBase* FactoryMicrosecondsTimeGet(const std::string& name,
156                                                    base::TimeDelta minimum,
157                                                    base::TimeDelta maximum,
158                                                    size_t bucket_count,
159                                                    int32_t flags);
160 
161   static HistogramBase* FactoryGet(const char* name,
162                                    Sample minimum,
163                                    Sample maximum,
164                                    size_t bucket_count,
165                                    int32_t flags);
166   static HistogramBase* FactoryTimeGet(const char* name,
167                                        base::TimeDelta minimum,
168                                        base::TimeDelta maximum,
169                                        size_t bucket_count,
170                                        int32_t flags);
171   static HistogramBase* FactoryMicrosecondsTimeGet(const char* name,
172                                                    base::TimeDelta minimum,
173                                                    base::TimeDelta maximum,
174                                                    size_t bucket_count,
175                                                    int32_t flags);
176 
177   // Create a histogram using data in persistent storage.
178   static std::unique_ptr<HistogramBase> PersistentCreate(
179       const char* name,
180       const BucketRanges* ranges,
181       const DelayedPersistentAllocation& counts,
182       const DelayedPersistentAllocation& logged_counts,
183       HistogramSamples::Metadata* meta,
184       HistogramSamples::Metadata* logged_meta);
185 
186   static void InitializeBucketRanges(Sample minimum,
187                                      Sample maximum,
188                                      BucketRanges* ranges);
189 
190   // This constant if for FindCorruption. Since snapshots of histograms are
191   // taken asynchronously relative to sampling, and our counting code currently
192   // does not prevent race conditions, it is pretty likely that we'll catch a
193   // redundant count that doesn't match the sample count.  We allow for a
194   // certain amount of slop before flagging this as an inconsistency. Even with
195   // an inconsistency, we'll snapshot it again (for UMA in about a half hour),
196   // so we'll eventually get the data, if it was not the result of a corruption.
197   static const int kCommonRaceBasedCountMismatch;
198 
199   // Check to see if bucket ranges, counts and tallies in the snapshot are
200   // consistent with the bucket ranges and checksums in our histogram.  This can
201   // produce a false-alarm if a race occurred in the reading of the data during
202   // a SnapShot process, but should otherwise be false at all times (unless we
203   // have memory over-writes, or DRAM failures). Flag definitions are located
204   // under "enum Inconsistency" in base/metrics/histogram_base.h.
205   uint32_t FindCorruption(const HistogramSamples& samples) const override;
206 
207   //----------------------------------------------------------------------------
208   // Accessors for factory construction, serialization and testing.
209   //----------------------------------------------------------------------------
210   const BucketRanges* bucket_ranges() const;
211   Sample declared_min() const;
212   Sample declared_max() const;
213   virtual Sample ranges(size_t i) const;
214   virtual size_t bucket_count() const;
215 
216   // This function validates histogram construction arguments. It returns false
217   // if some of the arguments are bad but also corrects them so they should
218   // function on non-dcheck builds without crashing.
219   // Note. Currently it allow some bad input, e.g. 0 as minimum, but silently
220   // converts it to good input: 1.
221   static bool InspectConstructionArguments(std::string_view name,
222                                            Sample* minimum,
223                                            Sample* maximum,
224                                            size_t* bucket_count);
225 
226   // HistogramBase implementation:
227   uint64_t name_hash() const override;
228   HistogramType GetHistogramType() const override;
229   bool HasConstructionArguments(Sample expected_minimum,
230                                 Sample expected_maximum,
231                                 size_t expected_bucket_count) const override;
232   void Add(Sample value) override;
233   void AddCount(Sample value, int count) override;
234   std::unique_ptr<HistogramSamples> SnapshotSamples() const override;
235   std::unique_ptr<HistogramSamples> SnapshotUnloggedSamples() const override;
236   void MarkSamplesAsLogged(const HistogramSamples& samples) final;
237   std::unique_ptr<HistogramSamples> SnapshotDelta() override;
238   std::unique_ptr<HistogramSamples> SnapshotFinalDelta() const override;
239   bool AddSamples(const HistogramSamples& samples) override;
240   bool AddSamplesFromPickle(base::PickleIterator* iter) override;
241   base::Value::Dict ToGraphDict() const override;
242 
243  protected:
244   // This class, defined entirely within the .cc file, contains all the
245   // common logic for building a Histogram and can be overridden by more
246   // specific types to alter details of how the creation is done. It is
247   // defined as an embedded class (rather than an anonymous one) so it
248   // can access the protected constructors.
249   class Factory;
250 
251   // |ranges| should contain the underflow and overflow buckets. See top
252   // comments for example.
253   Histogram(const char* name, const BucketRanges* ranges);
254 
255   // Traditionally, histograms allocate their own memory for the bucket
256   // vector but "shared" histograms use memory regions allocated from a
257   // special memory segment that is passed in here.  It is assumed that
258   // the life of this memory is managed externally and exceeds the lifetime
259   // of this object. Practically, this memory is never released until the
260   // process exits and the OS cleans it up.
261   Histogram(const char* name,
262             const BucketRanges* ranges,
263             const DelayedPersistentAllocation& counts,
264             const DelayedPersistentAllocation& logged_counts,
265             HistogramSamples::Metadata* meta,
266             HistogramSamples::Metadata* logged_meta);
267 
268   // HistogramBase implementation:
269   void SerializeInfoImpl(base::Pickle* pickle) const override;
270 
271   // Return a string description of what goes in a given bucket.
272   // Most commonly this is the numeric value, but in derived classes it may
273   // be a name (or string description) given to the bucket.
274   virtual std::string GetAsciiBucketRange(size_t it) const;
275 
276  private:
277   // Allow tests to corrupt our innards for testing purposes.
278   friend class HistogramTest;
279   friend class HistogramThreadsafeTest;
280   FRIEND_TEST_ALL_PREFIXES(HistogramTest, BoundsTest);
281   FRIEND_TEST_ALL_PREFIXES(HistogramTest, BucketPlacementTest);
282   FRIEND_TEST_ALL_PREFIXES(HistogramTest, CorruptSampleCounts);
283 
284   friend class StatisticsRecorder;  // To allow it to delete duplicates.
285   friend class StatisticsRecorderTest;
286 
287   friend BASE_EXPORT HistogramBase* DeserializeHistogramInfo(
288       base::PickleIterator* iter);
289   static HistogramBase* DeserializeInfoImpl(base::PickleIterator* iter);
290 
291   static HistogramBase* FactoryGetInternal(std::string_view name,
292                                            Sample minimum,
293                                            Sample maximum,
294                                            size_t bucket_count,
295                                            int32_t flags);
296   static HistogramBase* FactoryTimeGetInternal(std::string_view name,
297                                                base::TimeDelta minimum,
298                                                base::TimeDelta maximum,
299                                                size_t bucket_count,
300                                                int32_t flags);
301   static HistogramBase* FactoryMicrosecondsTimeGetInternal(
302       std::string_view name,
303       base::TimeDelta minimum,
304       base::TimeDelta maximum,
305       size_t bucket_count,
306       int32_t flags);
307 
308   // Create a snapshot containing all samples (both logged and unlogged).
309   // Implementation of SnapshotSamples method with a more specific type for
310   // internal use.
311   std::unique_ptr<SampleVector> SnapshotAllSamples() const;
312 
313   // Returns a copy of unlogged samples as the underlying SampleVector class,
314   // instead of the HistogramSamples base class. Used for tests and to avoid
315   // virtual dispatch from some callsites.
316   std::unique_ptr<SampleVector> SnapshotUnloggedSamplesImpl() const;
317 
318   // Writes the type, min, max, and bucket count information of the histogram in
319   // |params|.
320   Value::Dict GetParameters() const override;
321 
322   // Samples that have not yet been logged with SnapshotDelta().
323   std::unique_ptr<SampleVectorBase> unlogged_samples_;
324 
325   // Accumulation of all samples that have been logged with SnapshotDelta().
326   std::unique_ptr<SampleVectorBase> logged_samples_;
327 
328 #if DCHECK_IS_ON()  // Don't waste memory if it won't be used.
329   // Flag to indicate if PrepareFinalDelta has been previously called. It is
330   // used to DCHECK that a final delta is not created multiple times.
331   mutable bool final_delta_created_ = false;
332 #endif
333 };
334 
335 //------------------------------------------------------------------------------
336 
337 // LinearHistogram is a more traditional histogram, with evenly spaced
338 // buckets.
339 class BASE_EXPORT LinearHistogram : public Histogram {
340  public:
341   LinearHistogram(const LinearHistogram&) = delete;
342   LinearHistogram& operator=(const LinearHistogram&) = delete;
343 
344   ~LinearHistogram() override;
345 
346   /* minimum should start from 1. 0 is as minimum is invalid. 0 is an implicit
347      default underflow bucket. */
348   static HistogramBase* FactoryGet(std::string_view name,
349                                    Sample minimum,
350                                    Sample maximum,
351                                    size_t bucket_count,
352                                    int32_t flags);
353   static HistogramBase* FactoryTimeGet(std::string_view name,
354                                        TimeDelta minimum,
355                                        TimeDelta maximum,
356                                        size_t bucket_count,
357                                        int32_t flags);
358 
359   // Overloads of the above two functions that take a const std::string& or
360   // const char* |name| param, to avoid code bloat from the std::string
361   // constructor being inlined into call sites.
362   static HistogramBase* FactoryGet(const std::string& name,
363                                    Sample minimum,
364                                    Sample maximum,
365                                    size_t bucket_count,
366                                    int32_t flags);
367   static HistogramBase* FactoryTimeGet(const std::string& name,
368                                        TimeDelta minimum,
369                                        TimeDelta maximum,
370                                        size_t bucket_count,
371                                        int32_t flags);
372 
373   static HistogramBase* FactoryGet(const char* name,
374                                    Sample minimum,
375                                    Sample maximum,
376                                    size_t bucket_count,
377                                    int32_t flags);
378   static HistogramBase* FactoryTimeGet(const char* name,
379                                        TimeDelta minimum,
380                                        TimeDelta maximum,
381                                        size_t bucket_count,
382                                        int32_t flags);
383 
384   // Create a histogram using data in persistent storage.
385   static std::unique_ptr<HistogramBase> PersistentCreate(
386       const char* name,
387       const BucketRanges* ranges,
388       const DelayedPersistentAllocation& counts,
389       const DelayedPersistentAllocation& logged_counts,
390       HistogramSamples::Metadata* meta,
391       HistogramSamples::Metadata* logged_meta);
392 
393   struct DescriptionPair {
394     Sample sample;
395     const char* description;  // Null means end of a list of pairs.
396   };
397 
398   // Create a LinearHistogram and store a list of number/text values for use in
399   // writing the histogram graph.
400   // |descriptions| can be NULL, which means no special descriptions to set. If
401   // it's not NULL, the last element in the array must has a NULL in its
402   // "description" field.
403   static HistogramBase* FactoryGetWithRangeDescription(
404       std::string_view name,
405       Sample minimum,
406       Sample maximum,
407       size_t bucket_count,
408       int32_t flags,
409       const DescriptionPair descriptions[]);
410 
411   static void InitializeBucketRanges(Sample minimum,
412                                      Sample maximum,
413                                      BucketRanges* ranges);
414 
415   // Overridden from Histogram:
416   HistogramType GetHistogramType() const override;
417 
418  protected:
419   class Factory;
420 
421   LinearHistogram(const char* name, const BucketRanges* ranges);
422 
423   LinearHistogram(const char* name,
424                   const BucketRanges* ranges,
425                   const DelayedPersistentAllocation& counts,
426                   const DelayedPersistentAllocation& logged_counts,
427                   HistogramSamples::Metadata* meta,
428                   HistogramSamples::Metadata* logged_meta);
429 
430   // If we have a description for a bucket, then return that.  Otherwise
431   // let parent class provide a (numeric) description.
432   std::string GetAsciiBucketRange(size_t i) const override;
433 
434  private:
435   friend BASE_EXPORT HistogramBase* DeserializeHistogramInfo(
436       base::PickleIterator* iter);
437   static HistogramBase* DeserializeInfoImpl(base::PickleIterator* iter);
438 
439   static HistogramBase* FactoryGetInternal(std::string_view name,
440                                            Sample minimum,
441                                            Sample maximum,
442                                            size_t bucket_count,
443                                            int32_t flags);
444   static HistogramBase* FactoryTimeGetInternal(std::string_view name,
445                                                TimeDelta minimum,
446                                                TimeDelta maximum,
447                                                size_t bucket_count,
448                                                int32_t flags);
449 
450   // For some ranges, we store a printable description of a bucket range.
451   // If there is no description, then GetAsciiBucketRange() uses parent class
452   // to provide a description.
453   typedef std::map<Sample, std::string> BucketDescriptionMap;
454   BucketDescriptionMap bucket_description_;
455 };
456 
457 //------------------------------------------------------------------------------
458 
459 // ScaledLinearHistogram is a wrapper around a linear histogram that scales the
460 // counts down by some factor. Remainder values are kept locally but lost when
461 // uploaded or serialized. The integral counts are rounded up/down so should
462 // average to the correct value when many reports are added.
463 //
464 // This is most useful when adding many counts at once via AddCount() that can
465 // cause overflows of the 31-bit counters, usually with an enum as the value.
466 class BASE_EXPORT ScaledLinearHistogram {
467   using AtomicCount = Histogram::AtomicCount;
468   using Sample = Histogram::Sample;
469 
470  public:
471   // Currently only works with "exact" linear histograms: minimum=1, maximum=N,
472   // and bucket_count=N+1.
473   ScaledLinearHistogram(std::string_view name,
474                         Sample minimum,
475                         Sample maximum,
476                         size_t bucket_count,
477                         int32_t scale,
478                         int32_t flags);
479 
480   // Overload of the above function that take a const std::string& or const
481   // char* |name| param, to avoid code bloat from the std::string constructor
482   // being inlined into call sites.
483   ScaledLinearHistogram(const char* name,
484                         Sample minimum,
485                         Sample maximum,
486                         size_t bucket_count,
487                         int32_t scale,
488                         int32_t flags);
489   ScaledLinearHistogram(const std::string& name,
490                         Sample minimum,
491                         Sample maximum,
492                         size_t bucket_count,
493                         int32_t scale,
494                         int32_t flags);
495 
496   ScaledLinearHistogram(const ScaledLinearHistogram&) = delete;
497   ScaledLinearHistogram& operator=(const ScaledLinearHistogram&) = delete;
498 
499   ~ScaledLinearHistogram();
500 
501   // Like AddCount() but actually accumulates |count|/|scale| and increments
502   // the accumulated remainder by |count|%|scale|. An additional increment
503   // is done when the remainder has grown sufficiently large.
504   // The value after scaling must fit into 32-bit signed integer.
505   void AddScaledCount(Sample value, int64_t count);
506 
scale()507   int32_t scale() const { return scale_; }
histogram()508   HistogramBase* histogram() { return histogram_; }
509 
510  private:
511   // Pointer to the underlying histogram. Ownership of it remains with
512   // the statistics-recorder. This is typed as HistogramBase because it may be a
513   // DummyHistogram if expired.
514   const raw_ptr<HistogramBase> histogram_;
515 
516   // The scale factor of the sample counts.
517   const int32_t scale_;
518 
519   // A vector of "remainder" counts indexed by bucket number. These values
520   // may be negative as the scaled count is actually bumped once the
521   // remainder is 1/2 way to the scale value (thus "rounding").
522   std::vector<AtomicCount> remainders_;
523 };
524 
525 //------------------------------------------------------------------------------
526 
527 // BooleanHistogram is a histogram for booleans.
528 class BASE_EXPORT BooleanHistogram : public LinearHistogram {
529  public:
530   static HistogramBase* FactoryGet(std::string_view name, int32_t flags);
531 
532   // Overload of the above function that take a const std::string& or const
533   // char* |name| param, to avoid code bloat from the std::string constructor
534   // being inlined into call sites.
535   static HistogramBase* FactoryGet(const std::string& name, int32_t flags);
536   static HistogramBase* FactoryGet(const char* name, int32_t flags);
537 
538   BooleanHistogram(const BooleanHistogram&) = delete;
539   BooleanHistogram& operator=(const BooleanHistogram&) = delete;
540 
541   // Create a histogram using data in persistent storage.
542   static std::unique_ptr<HistogramBase> PersistentCreate(
543       const char* name,
544       const BucketRanges* ranges,
545       const DelayedPersistentAllocation& counts,
546       const DelayedPersistentAllocation& logged_counts,
547       HistogramSamples::Metadata* meta,
548       HistogramSamples::Metadata* logged_meta);
549 
550   HistogramType GetHistogramType() const override;
551 
552  protected:
553   class Factory;
554 
555  private:
556   static HistogramBase* FactoryGetInternal(std::string_view name,
557                                            int32_t flags);
558 
559   BooleanHistogram(const char* name, const BucketRanges* ranges);
560   BooleanHistogram(const char* name,
561                    const BucketRanges* ranges,
562                    const DelayedPersistentAllocation& counts,
563                    const DelayedPersistentAllocation& logged_counts,
564                    HistogramSamples::Metadata* meta,
565                    HistogramSamples::Metadata* logged_meta);
566 
567   friend BASE_EXPORT HistogramBase* DeserializeHistogramInfo(
568       base::PickleIterator* iter);
569   static HistogramBase* DeserializeInfoImpl(base::PickleIterator* iter);
570 };
571 
572 //------------------------------------------------------------------------------
573 
574 // CustomHistogram is a histogram for a set of custom integers.
575 class BASE_EXPORT CustomHistogram : public Histogram {
576  public:
577   // |custom_ranges| contains a vector of limits on ranges. Each limit should be
578   // > 0 and < kSampleType_MAX. (Currently 0 is still accepted for backward
579   // compatibility). The limits can be unordered or contain duplication, but
580   // client should not depend on this.
581   static HistogramBase* FactoryGet(std::string_view name,
582                                    const std::vector<Sample>& custom_ranges,
583                                    int32_t flags);
584 
585   // Overload of the above function that take a const std::string& or const
586   // char* |name| param, to avoid code bloat from the std::string constructor
587   // being inlined into call sites.
588   static HistogramBase* FactoryGet(const std::string& name,
589                                    const std::vector<Sample>& custom_ranges,
590                                    int32_t flags);
591   static HistogramBase* FactoryGet(const char* name,
592                                    const std::vector<Sample>& custom_ranges,
593                                    int32_t flags);
594 
595   CustomHistogram(const CustomHistogram&) = delete;
596   CustomHistogram& operator=(const CustomHistogram&) = delete;
597 
598   // Create a histogram using data in persistent storage.
599   static std::unique_ptr<HistogramBase> PersistentCreate(
600       const char* name,
601       const BucketRanges* ranges,
602       const DelayedPersistentAllocation& counts,
603       const DelayedPersistentAllocation& logged_counts,
604       HistogramSamples::Metadata* meta,
605       HistogramSamples::Metadata* logged_meta);
606 
607   // Overridden from Histogram:
608   HistogramType GetHistogramType() const override;
609 
610   // Helper method for transforming an array of valid enumeration values
611   // to the std::vector<int> expected by UMA_HISTOGRAM_CUSTOM_ENUMERATION.
612   // This function ensures that a guard bucket exists right after any
613   // valid sample value (unless the next higher sample is also a valid value),
614   // so that invalid samples never fall into the same bucket as valid samples.
615   static std::vector<Sample> ArrayToCustomEnumRanges(
616       base::span<const Sample> values);
617 
618  protected:
619   class Factory;
620 
621   CustomHistogram(const char* name, const BucketRanges* ranges);
622 
623   CustomHistogram(const char* name,
624                   const BucketRanges* ranges,
625                   const DelayedPersistentAllocation& counts,
626                   const DelayedPersistentAllocation& logged_counts,
627                   HistogramSamples::Metadata* meta,
628                   HistogramSamples::Metadata* logged_meta);
629 
630   // HistogramBase implementation:
631   void SerializeInfoImpl(base::Pickle* pickle) const override;
632 
633  private:
634   friend BASE_EXPORT HistogramBase* DeserializeHistogramInfo(
635       base::PickleIterator* iter);
636   static HistogramBase* DeserializeInfoImpl(base::PickleIterator* iter);
637 
638   static HistogramBase* FactoryGetInternal(
639       std::string_view name,
640       const std::vector<Sample>& custom_ranges,
641       int32_t flags);
642 
643   static bool ValidateCustomRanges(const std::vector<Sample>& custom_ranges);
644 };
645 
646 namespace internal {
647 
648 // Controls whether invocations of UMA_HISTOGRAM_SPLIT_BY_PROCESS_PRIORITY in
649 // this process log to their ".BestEffort" suffix or not. Timing metrics
650 // reported through UMA_HISTOGRAM_SPLIT_BY_PROCESS_PRIORITY which overlap a
651 // best-effort range will be suffixed with ".BestEffort".
652 BASE_EXPORT void SetSharedLastForegroundTimeForMetrics(
653     const std::atomic<TimeTicks>* last_foreground_time_ref);
654 
655 // Returns the pointer passed to SetSharedLastForegroundTimeForMetrics, or
656 // nullptr if it was never called.
657 BASE_EXPORT const std::atomic<TimeTicks>*
658 GetSharedLastForegroundTimeForMetricsForTesting();
659 
660 // Reports whether the interval [`now - range`, `now`] overlaps with a period
661 // where this process was running at Process::Priority::kBestEffort. Defaults to
662 // false if `last_foreground_time_ref` was never set (e.g. in processes not
663 // affected by priorities) but otherwise defaults to true if there's ambiguity
664 // (might have overlapped a best-effort range; as the reported timing might have
665 // been affected and shouldn't be reported as "definitely measured in
666 // foreground").
667 // This method is atomic and suitable for performance critical histogram
668 // samples.
669 BASE_EXPORT bool OverlapsBestEffortRange(TimeTicks now, TimeDelta range);
670 
671 }  // namespace internal
672 
673 }  // namespace base
674 
675 #endif  // BASE_METRICS_HISTOGRAM_H_
676