123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430 |
- // Copyright 2014 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #ifndef BASE_METRICS_HISTOGRAM_MACROS_H_
- #define BASE_METRICS_HISTOGRAM_MACROS_H_
- #include "base/macros.h"
- #include "base/metrics/histogram.h"
- #include "base/metrics/histogram_macros_internal.h"
- #include "base/metrics/histogram_macros_local.h"
- #include "base/time/time.h"
- // Macros for efficient use of histograms.
- //
- // For best practices on deciding when to emit to a histogram and what form
- // the histogram should take, see
- // https://chromium.googlesource.com/chromium/src.git/+/HEAD/tools/metrics/histograms/README.md
- // All of these macros must be called with |name| as a runtime constant - it
- // doesn't have to literally be a constant, but it must be the same string on
- // all calls from a particular call site. If this rule is violated, it is
- // possible the data will be written to the wrong histogram.
- //------------------------------------------------------------------------------
- // Enumeration histograms.
- // These macros create histograms for enumerated data. Ideally, the data should
- // be of the form of "event occurs, log the result". We recommended not putting
- // related but not directly connected data as enums within the same histogram.
- // You should be defining an associated Enum, and the input sample should be
- // an element of the Enum.
- // All of these macros must be called with |name| as a runtime constant.
- // The first variant of UMA_HISTOGRAM_ENUMERATION accepts two arguments: the
- // histogram name and the enum sample. It deduces the correct boundary value to
- // use by looking for an enumerator with the name kMaxValue. kMaxValue should
- // share the value of the highest enumerator: this avoids switch statements
- // having to handle a sentinel no-op value.
- //
- // Sample usage:
- // // These values are logged to UMA. Entries should not be renumbered and
- // // numeric values should never be reused. Please keep in sync with "MyEnum"
- // // in src/tools/metrics/histograms/enums.xml.
- // enum class MyEnum {
- // kFirstValue = 0,
- // kSecondValue = 1,
- // ...
- // kFinalValue = N,
- // kMaxValue = kFinalValue,
- // };
- // UMA_HISTOGRAM_ENUMERATION("My.Enumeration", MyEnum::kSomeValue);
- //
- // The second variant requires three arguments: the first two are the same as
- // before, and the third argument is the enum boundary: this must be strictly
- // greater than any other enumerator that will be sampled.
- //
- // Sample usage:
- // // These values are logged to UMA. Entries should not be renumbered and
- // // numeric values should never be reused. Please keep in sync with "MyEnum"
- // // in src/tools/metrics/histograms/enums.xml.
- // enum class MyEnum {
- // FIRST_VALUE = 0,
- // SECOND_VALUE = 1,
- // ...
- // FINAL_VALUE = N,
- // COUNT
- // };
- // UMA_HISTOGRAM_ENUMERATION("My.Enumeration",
- // MyEnum::SOME_VALUE, MyEnum::COUNT);
- //
- // Note: If the enum is used in a switch, it is often desirable to avoid writing
- // a case statement to handle an unused sentinel value (i.e. COUNT in the above
- // example). For scoped enums, this is awkward since it requires casting the
- // enum to an arithmetic type and adding one. Instead, prefer the two argument
- // version of the macro which automatically deduces the boundary from kMaxValue.
- #define UMA_HISTOGRAM_ENUMERATION(name, ...) \
- INTERNAL_UMA_HISTOGRAM_ENUMERATION_GET_MACRO( \
- __VA_ARGS__, INTERNAL_UMA_HISTOGRAM_ENUMERATION_SPECIFY_BOUNDARY, \
- INTERNAL_UMA_HISTOGRAM_ENUMERATION_DEDUCE_BOUNDARY) \
- (name, __VA_ARGS__, base::HistogramBase::kUmaTargetedHistogramFlag)
- // As above but "scaled" count to avoid overflows caused by increments of
- // large amounts. See UMA_HISTOGRAM_SCALED_EXACT_LINEAR for more information.
- // Only the new format utilizing an internal kMaxValue is supported.
- // It'll be necessary to #include "base/lazy_instance.h" to use this macro.
- // name: Full constant name of the histogram (must not change between calls).
- // sample: Bucket to be incremented.
- // count: Amount by which to increment.
- // scale: Amount by which |count| is divided.
- // Sample usage:
- // UMA_HISTOGRAM_SCALED_ENUMERATION("FooKiB", kEnumValue, byte_count, 1024)
- #define UMA_HISTOGRAM_SCALED_ENUMERATION(name, sample, count, scale) \
- INTERNAL_HISTOGRAM_SCALED_ENUMERATION_WITH_FLAG( \
- name, sample, count, scale, \
- base::HistogramBase::kUmaTargetedHistogramFlag)
- // Histogram for boolean values.
- // Sample usage:
- // UMA_HISTOGRAM_BOOLEAN("Histogram.Boolean", bool);
- #define UMA_HISTOGRAM_BOOLEAN(name, sample) \
- STATIC_HISTOGRAM_POINTER_BLOCK(name, AddBoolean(sample), \
- base::BooleanHistogram::FactoryGet(name, \
- base::HistogramBase::kUmaTargetedHistogramFlag))
- //------------------------------------------------------------------------------
- // Linear histograms.
- // All of these macros must be called with |name| as a runtime constant.
- // Used for capturing integer data with a linear bucketing scheme. This can be
- // used when you want the exact value of some small numeric count, with a max of
- // 100 or less. If you need to capture a range of greater than 100, we recommend
- // the use of the COUNT histograms below.
- // Sample usage:
- // UMA_HISTOGRAM_EXACT_LINEAR("Histogram.Linear", count, 10);
- #define UMA_HISTOGRAM_EXACT_LINEAR(name, sample, value_max) \
- INTERNAL_HISTOGRAM_EXACT_LINEAR_WITH_FLAG( \
- name, sample, value_max, base::HistogramBase::kUmaTargetedHistogramFlag)
- // Used for capturing basic percentages. This will be 100 buckets of size 1.
- // Sample usage:
- // UMA_HISTOGRAM_PERCENTAGE("Histogram.Percent", percent_as_int);
- #define UMA_HISTOGRAM_PERCENTAGE(name, percent_as_int) \
- UMA_HISTOGRAM_EXACT_LINEAR(name, percent_as_int, 101)
- //------------------------------------------------------------------------------
- // Scaled linear histograms.
- // These take |count| and |scale| parameters to allow cumulative reporting of
- // large numbers. For example, code might pass a count of 1825 bytes and a scale
- // of 1024 bytes to report values in kilobytes. Only the scaled count is
- // reported, but the remainder is tracked between calls, so that multiple calls
- // will accumulate correctly. Only "exact linear" is supported.
- // It'll be necessary to #include "base/lazy_instance.h" to use this macro.
- // name: Full constant name of the histogram (must not change between calls).
- // sample: Bucket to be incremented.
- // count: Amount by which to increment.
- // sample_max: Maximum (exclusive) allowed sample value.
- // scale: Amount by which |count| is divided.
- // Sample usage:
- // UMA_HISTOGRAM_SCALED_EXACT_LINER("FooKiB", bucket_no, byte_count,
- // kBucketsMax+1, 1024)
- #define UMA_HISTOGRAM_SCALED_EXACT_LINEAR(name, sample, count, sample_max, \
- scale) \
- INTERNAL_HISTOGRAM_SCALED_EXACT_LINEAR_WITH_FLAG( \
- name, sample, count, sample_max, scale, \
- base::HistogramBase::kUmaTargetedHistogramFlag)
- //------------------------------------------------------------------------------
- // Count histograms. These are used for collecting numeric data. Note that we
- // have macros for more specialized use cases below (memory, time, percentages).
- // The number suffixes here refer to the max size of the sample, i.e. COUNT_1000
- // will be able to collect samples of counts up to 1000. The default number of
- // buckets in all default macros is 50. We recommend erring on the side of too
- // large a range versus too short a range.
- // These macros default to exponential histograms - i.e. the lengths of the
- // bucket ranges exponentially increase as the sample range increases.
- // These should *not* be used if you are interested in exact counts, i.e. a
- // bucket range of 1. In these cases, you should use the ENUMERATION macros
- // defined later. These should also not be used to capture the number of some
- // event, i.e. "button X was clicked N times". In this cases, an enum should be
- // used, ideally with an appropriate baseline enum entry included.
- // All of these macros must be called with |name| as a runtime constant.
- // Sample usage:
- // UMA_HISTOGRAM_COUNTS_1M("My.Histogram", sample);
- #define UMA_HISTOGRAM_COUNTS_100(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
- name, sample, 1, 100, 50)
- #define UMA_HISTOGRAM_COUNTS_1000(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
- name, sample, 1, 1000, 50)
- #define UMA_HISTOGRAM_COUNTS_10000(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
- name, sample, 1, 10000, 50)
- #define UMA_HISTOGRAM_COUNTS_100000(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
- name, sample, 1, 100000, 50)
- #define UMA_HISTOGRAM_COUNTS_1M(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
- name, sample, 1, 1000000, 50)
- #define UMA_HISTOGRAM_COUNTS_10M(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
- name, sample, 1, 10000000, 50)
- // This can be used when the default ranges are not sufficient. This macro lets
- // the metric developer customize the min and max of the sampled range, as well
- // as the number of buckets recorded.
- // Any data outside the range here will be put in underflow and overflow
- // buckets. Min values should be >=1 as emitted 0s will still go into the
- // underflow bucket.
- // Sample usage:
- // UMA_HISTOGRAM_CUSTOM_COUNTS("My.Histogram", sample, 1, 100000000, 50);
- #define UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \
- INTERNAL_HISTOGRAM_CUSTOM_COUNTS_WITH_FLAG( \
- name, sample, min, max, bucket_count, \
- base::HistogramBase::kUmaTargetedHistogramFlag)
- //------------------------------------------------------------------------------
- // Timing histograms. These are used for collecting timing data (generally
- // latencies).
- // These macros create exponentially sized histograms (lengths of the bucket
- // ranges exponentially increase as the sample range increases). The input
- // sample is a base::TimeDelta. The output data is measured in ms granularity.
- // All of these macros must be called with |name| as a runtime constant.
- // Sample usage:
- // UMA_HISTOGRAM_TIMES("My.Timing.Histogram", time_delta);
- // Short timings - up to 10 seconds. For high-resolution (microseconds) timings,
- // see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES.
- #define UMA_HISTOGRAM_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \
- name, sample, base::TimeDelta::FromMilliseconds(1), \
- base::TimeDelta::FromSeconds(10), 50)
- // Medium timings - up to 3 minutes. Note this starts at 10ms (no good reason,
- // but not worth changing).
- #define UMA_HISTOGRAM_MEDIUM_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \
- name, sample, base::TimeDelta::FromMilliseconds(10), \
- base::TimeDelta::FromMinutes(3), 50)
- // Long timings - up to an hour.
- #define UMA_HISTOGRAM_LONG_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \
- name, sample, base::TimeDelta::FromMilliseconds(1), \
- base::TimeDelta::FromHours(1), 50)
- // Long timings with higher granularity - up to an hour with 100 buckets.
- #define UMA_HISTOGRAM_LONG_TIMES_100(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \
- name, sample, base::TimeDelta::FromMilliseconds(1), \
- base::TimeDelta::FromHours(1), 100)
- // This can be used when the default ranges are not sufficient. This macro lets
- // the metric developer customize the min and max of the sampled range, as well
- // as the number of buckets recorded.
- // Sample usage:
- // UMA_HISTOGRAM_CUSTOM_TIMES("Very.Long.Timing.Histogram", time_delta,
- // base::TimeDelta::FromSeconds(1), base::TimeDelta::FromDays(1), 100);
- #define UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \
- STATIC_HISTOGRAM_POINTER_BLOCK( \
- name, AddTimeMillisecondsGranularity(sample), \
- base::Histogram::FactoryTimeGet( \
- name, min, max, bucket_count, \
- base::HistogramBase::kUmaTargetedHistogramFlag))
- // Same as UMA_HISTOGRAM_CUSTOM_TIMES but reports |sample| in microseconds,
- // dropping the report if this client doesn't have a high-resolution clock.
- //
- // Note: dropping reports on clients with low-resolution clocks means these
- // reports will be biased to a portion of the population on Windows. See
- // Windows.HasHighResolutionTimeTicks for the affected sample.
- //
- // Sample usage:
- // UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
- // "High.Resolution.TimingMicroseconds.Histogram", time_delta,
- // base::TimeDelta::FromMicroseconds(1),
- // base::TimeDelta::FromMilliseconds(10), 100);
- #define UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(name, sample, min, max, \
- bucket_count) \
- STATIC_HISTOGRAM_POINTER_BLOCK( \
- name, AddTimeMicrosecondsGranularity(sample), \
- base::Histogram::FactoryMicrosecondsTimeGet( \
- name, min, max, bucket_count, \
- base::HistogramBase::kUmaTargetedHistogramFlag))
- // Scoped class which logs its time on this earth in milliseconds as a UMA
- // statistic. This is recommended for when you want a histogram which measures
- // the time it takes for a method to execute. This measures up to 10 seconds. It
- // uses UMA_HISTOGRAM_TIMES under the hood.
- // Sample usage:
- // void Function() {
- // SCOPED_UMA_HISTOGRAM_TIMER("Component.FunctionTime");
- // ...
- // }
- enum class ScopedHistogramTiming {
- kMicrosecondTimes,
- kMediumTimes,
- kLongTimes
- };
- #define SCOPED_UMA_HISTOGRAM_TIMER(name) \
- INTERNAL_SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER( \
- name, ScopedHistogramTiming::kMediumTimes, __COUNTER__)
- // Similar scoped histogram timer, but this uses UMA_HISTOGRAM_LONG_TIMES_100,
- // which measures up to an hour, and uses 100 buckets. This is more expensive
- // to store, so only use if this often takes >10 seconds.
- #define SCOPED_UMA_HISTOGRAM_LONG_TIMER(name) \
- INTERNAL_SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER( \
- name, ScopedHistogramTiming::kLongTimes, __COUNTER__)
- // Similar scoped histogram timer, but this uses
- // UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES, measuring from 1 microseconds to 1
- // second, with 50 buckets.
- #define SCOPED_UMA_HISTOGRAM_SHORT_TIMER(name) \
- INTERNAL_SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER( \
- name, ScopedHistogramTiming::kMicrosecondTimes, __COUNTER__)
- //------------------------------------------------------------------------------
- // Memory histograms.
- // These macros create exponentially sized histograms (lengths of the bucket
- // ranges exponentially increase as the sample range increases). The input
- // sample must be a number measured in kilobytes.
- // All of these macros must be called with |name| as a runtime constant.
- // Sample usage:
- // UMA_HISTOGRAM_MEMORY_KB("My.Memory.Histogram", memory_in_kb);
- // Used to measure common KB-granularity memory stats. Range is up to 500000KB -
- // approximately 500M.
- #define UMA_HISTOGRAM_MEMORY_KB(name, sample) \
- UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, 1000, 500000, 50)
- // Used to measure common MB-granularity memory stats. Range is up to ~64G.
- #define UMA_HISTOGRAM_MEMORY_LARGE_MB(name, sample) \
- UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, 1, 64000, 100)
- //------------------------------------------------------------------------------
- // Stability-specific histograms.
- // Histograms logged in as stability histograms will be included in the initial
- // stability log. See comments by declaration of
- // MetricsService::PrepareInitialStabilityLog().
- // All of these macros must be called with |name| as a runtime constant.
- // For details on usage, see the documentation on the non-stability equivalents.
- #define UMA_STABILITY_HISTOGRAM_BOOLEAN(name, sample) \
- STATIC_HISTOGRAM_POINTER_BLOCK( \
- name, AddBoolean(sample), \
- base::BooleanHistogram::FactoryGet( \
- name, base::HistogramBase::kUmaStabilityHistogramFlag))
- #define UMA_STABILITY_HISTOGRAM_COUNTS_100(name, sample) \
- UMA_STABILITY_HISTOGRAM_CUSTOM_COUNTS(name, sample, 1, 100, 50)
- #define UMA_STABILITY_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, \
- bucket_count) \
- INTERNAL_HISTOGRAM_CUSTOM_COUNTS_WITH_FLAG( \
- name, sample, min, max, bucket_count, \
- base::HistogramBase::kUmaStabilityHistogramFlag)
- #define UMA_STABILITY_HISTOGRAM_ENUMERATION(name, ...) \
- INTERNAL_UMA_HISTOGRAM_ENUMERATION_GET_MACRO( \
- __VA_ARGS__, INTERNAL_UMA_HISTOGRAM_ENUMERATION_SPECIFY_BOUNDARY, \
- INTERNAL_UMA_HISTOGRAM_ENUMERATION_DEDUCE_BOUNDARY) \
- (name, __VA_ARGS__, base::HistogramBase::kUmaStabilityHistogramFlag)
- #define UMA_STABILITY_HISTOGRAM_LONG_TIMES(name, sample) \
- STATIC_HISTOGRAM_POINTER_BLOCK( \
- name, AddTimeMillisecondsGranularity(sample), \
- base::Histogram::FactoryTimeGet( \
- name, base::TimeDelta::FromMilliseconds(1), \
- base::TimeDelta::FromHours(1), 50, \
- base::HistogramBase::kUmaStabilityHistogramFlag))
- #define UMA_STABILITY_HISTOGRAM_PERCENTAGE(name, percent_as_int) \
- INTERNAL_HISTOGRAM_EXACT_LINEAR_WITH_FLAG( \
- name, percent_as_int, 101, \
- base::HistogramBase::kUmaStabilityHistogramFlag)
- //------------------------------------------------------------------------------
- // Histogram instantiation helpers.
- // Support a collection of histograms, perhaps one for each entry in an
- // enumeration. This macro manages a block of pointers, adding to a specific
- // one by its index.
- //
- // A typical instantiation looks something like this:
- // STATIC_HISTOGRAM_POINTER_GROUP(
- // GetHistogramNameForIndex(histogram_index),
- // histogram_index, MAXIMUM_HISTOGRAM_INDEX, Add(some_delta),
- // base::Histogram::FactoryGet(
- // GetHistogramNameForIndex(histogram_index),
- // MINIMUM_SAMPLE, MAXIMUM_SAMPLE, BUCKET_COUNT,
- // base::HistogramBase::kUmaTargetedHistogramFlag));
- //
- // Though it seems inefficient to generate the name twice, the first
- // instance will be used only for DCHECK builds and the second will
- // execute only during the first access to the given index, after which
- // the pointer is cached and the name never needed again.
- #define STATIC_HISTOGRAM_POINTER_GROUP( \
- constant_histogram_name, index, constant_maximum, \
- histogram_add_method_invocation, histogram_factory_get_invocation) \
- do { \
- static std::atomic_uintptr_t atomic_histograms[constant_maximum]; \
- DCHECK_LE(0, index); \
- DCHECK_LT(index, constant_maximum); \
- HISTOGRAM_POINTER_USE( \
- std::addressof(atomic_histograms[index]), constant_histogram_name, \
- histogram_add_method_invocation, histogram_factory_get_invocation); \
- } while (0)
- //------------------------------------------------------------------------------
- // Deprecated histogram macros. Not recommended for current use.
- // Legacy name for UMA_HISTOGRAM_COUNTS_1M. Suggest using explicit naming
- // and not using this macro going forward.
- #define UMA_HISTOGRAM_COUNTS(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
- name, sample, 1, 1000000, 50)
- // MB-granularity memory metric. This has a short max (1G).
- #define UMA_HISTOGRAM_MEMORY_MB(name, sample) \
- UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, 1, 1000, 50)
- // For an enum with customized range. In general, sparse histograms should be
- // used instead.
- // Samples should be one of the std::vector<int> list provided via
- // |custom_ranges|. See comments above CustomRanges::FactoryGet about the
- // requirement of |custom_ranges|. You can use the helper function
- // CustomHistogram::ArrayToCustomEnumRanges to transform a C-style array of
- // valid sample values to a std::vector<int>.
- #define UMA_HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \
- STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \
- base::CustomHistogram::FactoryGet(name, custom_ranges, \
- base::HistogramBase::kUmaTargetedHistogramFlag))
- #endif // BASE_METRICS_HISTOGRAM_MACROS_H_
|