xref: /aosp_15_r20/external/cronet/base/metrics/histogram_macros_internal.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2016 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_METRICS_HISTOGRAM_MACROS_INTERNAL_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_METRICS_HISTOGRAM_MACROS_INTERNAL_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include <atomic>
11*6777b538SAndroid Build Coastguard Worker #include <limits>
12*6777b538SAndroid Build Coastguard Worker #include <memory>
13*6777b538SAndroid Build Coastguard Worker #include <type_traits>
14*6777b538SAndroid Build Coastguard Worker 
15*6777b538SAndroid Build Coastguard Worker #include "base/dcheck_is_on.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/metrics/sparse_histogram.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
19*6777b538SAndroid Build Coastguard Worker 
20*6777b538SAndroid Build Coastguard Worker // This is for macros and helpers internal to base/metrics. They should not be
21*6777b538SAndroid Build Coastguard Worker // used outside of this directory. For writing to UMA histograms, see
22*6777b538SAndroid Build Coastguard Worker // histogram_macros.h.
23*6777b538SAndroid Build Coastguard Worker 
24*6777b538SAndroid Build Coastguard Worker namespace base {
25*6777b538SAndroid Build Coastguard Worker namespace internal {
26*6777b538SAndroid Build Coastguard Worker 
27*6777b538SAndroid Build Coastguard Worker // Helper traits for deducing the boundary value for enums.
28*6777b538SAndroid Build Coastguard Worker template <typename Enum, typename SFINAE = void>
29*6777b538SAndroid Build Coastguard Worker struct EnumSizeTraits {
CountEnumSizeTraits30*6777b538SAndroid Build Coastguard Worker   static constexpr Enum Count() {
31*6777b538SAndroid Build Coastguard Worker     static_assert(
32*6777b538SAndroid Build Coastguard Worker         sizeof(Enum) == 0,
33*6777b538SAndroid Build Coastguard Worker         "enumerator must define kMaxValue enumerator to use this macro!");
34*6777b538SAndroid Build Coastguard Worker     return Enum();
35*6777b538SAndroid Build Coastguard Worker   }
36*6777b538SAndroid Build Coastguard Worker };
37*6777b538SAndroid Build Coastguard Worker 
38*6777b538SAndroid Build Coastguard Worker // Since the UMA histogram macros expect a value one larger than the max defined
39*6777b538SAndroid Build Coastguard Worker // enumerator value, add one.
40*6777b538SAndroid Build Coastguard Worker template <typename Enum>
41*6777b538SAndroid Build Coastguard Worker struct EnumSizeTraits<
42*6777b538SAndroid Build Coastguard Worker     Enum,
43*6777b538SAndroid Build Coastguard Worker     std::enable_if_t<std::is_enum_v<decltype(Enum::kMaxValue)>>> {
44*6777b538SAndroid Build Coastguard Worker   static constexpr Enum Count() {
45*6777b538SAndroid Build Coastguard Worker     // If you're getting
46*6777b538SAndroid Build Coastguard Worker     //   note: integer value X is outside the valid range of values [0, X] for
47*6777b538SAndroid Build Coastguard Worker     //         this enumeration type
48*6777b538SAndroid Build Coastguard Worker     // Then you need to give your enum a fixed underlying type.
49*6777b538SAndroid Build Coastguard Worker     return static_cast<Enum>(
50*6777b538SAndroid Build Coastguard Worker         static_cast<std::underlying_type_t<Enum>>(Enum::kMaxValue) + 1);
51*6777b538SAndroid Build Coastguard Worker   }
52*6777b538SAndroid Build Coastguard Worker };
53*6777b538SAndroid Build Coastguard Worker 
54*6777b538SAndroid Build Coastguard Worker }  // namespace internal
55*6777b538SAndroid Build Coastguard Worker }  // namespace base
56*6777b538SAndroid Build Coastguard Worker 
57*6777b538SAndroid Build Coastguard Worker // TODO(rkaplow): Improve commenting of these methods.
58*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
59*6777b538SAndroid Build Coastguard Worker // Histograms are often put in areas where they are called many many times, and
60*6777b538SAndroid Build Coastguard Worker // performance is critical.  As a result, they are designed to have a very low
61*6777b538SAndroid Build Coastguard Worker // recurring cost of executing (adding additional samples). Toward that end,
62*6777b538SAndroid Build Coastguard Worker // the macros declare a static pointer to the histogram in question, and only
63*6777b538SAndroid Build Coastguard Worker // take a "slow path" to construct (or find) the histogram on the first run
64*6777b538SAndroid Build Coastguard Worker // through the macro. We leak the histograms at shutdown time so that we don't
65*6777b538SAndroid Build Coastguard Worker // have to validate using the pointers at any time during the running of the
66*6777b538SAndroid Build Coastguard Worker // process.
67*6777b538SAndroid Build Coastguard Worker 
68*6777b538SAndroid Build Coastguard Worker // In some cases (integration into 3rd party code), it's useful to separate the
69*6777b538SAndroid Build Coastguard Worker // definition of |atomic_histogram_pointer| from its use. To achieve this we
70*6777b538SAndroid Build Coastguard Worker // define HISTOGRAM_POINTER_USE, which uses an |atomic_histogram_pointer|, and
71*6777b538SAndroid Build Coastguard Worker // STATIC_HISTOGRAM_POINTER_BLOCK, which defines an |atomic_histogram_pointer|
72*6777b538SAndroid Build Coastguard Worker // and forwards to HISTOGRAM_POINTER_USE.
73*6777b538SAndroid Build Coastguard Worker #define HISTOGRAM_POINTER_USE(                                           \
74*6777b538SAndroid Build Coastguard Worker     atomic_histogram_pointer, constant_histogram_name,                   \
75*6777b538SAndroid Build Coastguard Worker     histogram_add_method_invocation, histogram_factory_get_invocation)   \
76*6777b538SAndroid Build Coastguard Worker   do {                                                                   \
77*6777b538SAndroid Build Coastguard Worker     base::HistogramBase* histogram_pointer(                              \
78*6777b538SAndroid Build Coastguard Worker         reinterpret_cast<base::HistogramBase*>(                          \
79*6777b538SAndroid Build Coastguard Worker             atomic_histogram_pointer->load(std::memory_order_acquire))); \
80*6777b538SAndroid Build Coastguard Worker     if (!histogram_pointer) {                                            \
81*6777b538SAndroid Build Coastguard Worker       /*                                                                 \
82*6777b538SAndroid Build Coastguard Worker        * This is the slow path, which will construct OR find the         \
83*6777b538SAndroid Build Coastguard Worker        * matching histogram. |histogram_factory_get_invocation| includes \
84*6777b538SAndroid Build Coastguard Worker        * locks on a global histogram name map and is completely thread   \
85*6777b538SAndroid Build Coastguard Worker        * safe.                                                           \
86*6777b538SAndroid Build Coastguard Worker        */                                                                \
87*6777b538SAndroid Build Coastguard Worker       histogram_pointer = histogram_factory_get_invocation;              \
88*6777b538SAndroid Build Coastguard Worker                                                                          \
89*6777b538SAndroid Build Coastguard Worker       /*                                                                 \
90*6777b538SAndroid Build Coastguard Worker        * We could do this without any barrier, since FactoryGet()        \
91*6777b538SAndroid Build Coastguard Worker        * entered and exited a lock after construction, but this barrier  \
92*6777b538SAndroid Build Coastguard Worker        * makes things clear.                                             \
93*6777b538SAndroid Build Coastguard Worker        */                                                                \
94*6777b538SAndroid Build Coastguard Worker       atomic_histogram_pointer->store(                                   \
95*6777b538SAndroid Build Coastguard Worker           reinterpret_cast<uintptr_t>(histogram_pointer),                \
96*6777b538SAndroid Build Coastguard Worker           std::memory_order_release);                                    \
97*6777b538SAndroid Build Coastguard Worker     }                                                                    \
98*6777b538SAndroid Build Coastguard Worker     if (DCHECK_IS_ON())                                                  \
99*6777b538SAndroid Build Coastguard Worker       histogram_pointer->CheckName(constant_histogram_name);             \
100*6777b538SAndroid Build Coastguard Worker     histogram_pointer->histogram_add_method_invocation;                  \
101*6777b538SAndroid Build Coastguard Worker   } while (0)
102*6777b538SAndroid Build Coastguard Worker 
103*6777b538SAndroid Build Coastguard Worker // This is a helper macro used by other macros and shouldn't be used directly.
104*6777b538SAndroid Build Coastguard Worker // Defines the static |atomic_histogram_pointer| and forwards to
105*6777b538SAndroid Build Coastguard Worker // HISTOGRAM_POINTER_USE.
106*6777b538SAndroid Build Coastguard Worker #define STATIC_HISTOGRAM_POINTER_BLOCK(constant_histogram_name,               \
107*6777b538SAndroid Build Coastguard Worker                                        histogram_add_method_invocation,       \
108*6777b538SAndroid Build Coastguard Worker                                        histogram_factory_get_invocation)      \
109*6777b538SAndroid Build Coastguard Worker   do {                                                                        \
110*6777b538SAndroid Build Coastguard Worker     /*                                                                        \
111*6777b538SAndroid Build Coastguard Worker      * The pointer's presence indicates that the initialization is complete.  \
112*6777b538SAndroid Build Coastguard Worker      * Initialization is idempotent, so it can safely be atomically repeated. \
113*6777b538SAndroid Build Coastguard Worker      */                                                                       \
114*6777b538SAndroid Build Coastguard Worker     static std::atomic_uintptr_t atomic_histogram_pointer;                    \
115*6777b538SAndroid Build Coastguard Worker     HISTOGRAM_POINTER_USE(                                                    \
116*6777b538SAndroid Build Coastguard Worker         std::addressof(atomic_histogram_pointer), constant_histogram_name,    \
117*6777b538SAndroid Build Coastguard Worker         histogram_add_method_invocation, histogram_factory_get_invocation);   \
118*6777b538SAndroid Build Coastguard Worker   } while (0)
119*6777b538SAndroid Build Coastguard Worker 
120*6777b538SAndroid Build Coastguard Worker // This is a helper macro used by other macros and shouldn't be used directly.
121*6777b538SAndroid Build Coastguard Worker #define INTERNAL_HISTOGRAM_CUSTOM_COUNTS_WITH_FLAG(name, sample, min, max,     \
122*6777b538SAndroid Build Coastguard Worker                                                    bucket_count, flag)         \
123*6777b538SAndroid Build Coastguard Worker     STATIC_HISTOGRAM_POINTER_BLOCK(                                            \
124*6777b538SAndroid Build Coastguard Worker         name, Add(sample),                                                     \
125*6777b538SAndroid Build Coastguard Worker         base::Histogram::FactoryGet(name, min, max, bucket_count, flag))
126*6777b538SAndroid Build Coastguard Worker 
127*6777b538SAndroid Build Coastguard Worker // This is a helper macro used by other macros and shouldn't be used directly.
128*6777b538SAndroid Build Coastguard Worker // The bucketing scheme is linear with a bucket size of 1. For N items,
129*6777b538SAndroid Build Coastguard Worker // recording values in the range [0, N - 1] creates a linear histogram with N +
130*6777b538SAndroid Build Coastguard Worker // 1 buckets:
131*6777b538SAndroid Build Coastguard Worker //   [0, 1), [1, 2), ..., [N - 1, N)
132*6777b538SAndroid Build Coastguard Worker // and an overflow bucket [N, infinity).
133*6777b538SAndroid Build Coastguard Worker //
134*6777b538SAndroid Build Coastguard Worker // Code should never emit to the overflow bucket; only to the other N buckets.
135*6777b538SAndroid Build Coastguard Worker // This allows future versions of Chrome to safely increase the boundary size.
136*6777b538SAndroid Build Coastguard Worker // Otherwise, the histogram would have [N - 1, infinity) as its overflow bucket,
137*6777b538SAndroid Build Coastguard Worker // and so the maximal value (N - 1) would be emitted to this overflow bucket.
138*6777b538SAndroid Build Coastguard Worker // But, if an additional value were later added, the bucket label for
139*6777b538SAndroid Build Coastguard Worker // the value (N - 1) would change to [N - 1, N), which would result in different
140*6777b538SAndroid Build Coastguard Worker // versions of Chrome using different bucket labels for identical data.
141*6777b538SAndroid Build Coastguard Worker #define INTERNAL_HISTOGRAM_EXACT_LINEAR_WITH_FLAG(name, sample, boundary,  \
142*6777b538SAndroid Build Coastguard Worker                                                   flag)                    \
143*6777b538SAndroid Build Coastguard Worker   do {                                                                     \
144*6777b538SAndroid Build Coastguard Worker     static_assert(!std::is_enum_v<std::decay_t<decltype(sample)>>,         \
145*6777b538SAndroid Build Coastguard Worker                   "|sample| should not be an enum type!");                 \
146*6777b538SAndroid Build Coastguard Worker     static_assert(!std::is_enum_v<std::decay_t<decltype(boundary)>>,       \
147*6777b538SAndroid Build Coastguard Worker                   "|boundary| should not be an enum type!");               \
148*6777b538SAndroid Build Coastguard Worker     STATIC_HISTOGRAM_POINTER_BLOCK(                                        \
149*6777b538SAndroid Build Coastguard Worker         name, Add(sample),                                                 \
150*6777b538SAndroid Build Coastguard Worker         base::LinearHistogram::FactoryGet(name, 1, boundary, boundary + 1, \
151*6777b538SAndroid Build Coastguard Worker                                           flag));                          \
152*6777b538SAndroid Build Coastguard Worker   } while (0)
153*6777b538SAndroid Build Coastguard Worker 
154*6777b538SAndroid Build Coastguard Worker // While this behaves the same as the above macro, the wrapping of a linear
155*6777b538SAndroid Build Coastguard Worker // histogram with another object to do the scaling means the POINTER_BLOCK
156*6777b538SAndroid Build Coastguard Worker // macro can't be used as it is tied to HistogramBase
157*6777b538SAndroid Build Coastguard Worker #define INTERNAL_HISTOGRAM_SCALED_EXACT_LINEAR_WITH_FLAG(                      \
158*6777b538SAndroid Build Coastguard Worker     name, sample, count, boundary, scale, flag)                                \
159*6777b538SAndroid Build Coastguard Worker   do {                                                                         \
160*6777b538SAndroid Build Coastguard Worker     static_assert(!std::is_enum_v<std::decay_t<decltype(sample)>>,             \
161*6777b538SAndroid Build Coastguard Worker                   "|sample| should not be an enum type!");                     \
162*6777b538SAndroid Build Coastguard Worker     static_assert(!std::is_enum_v<std::decay_t<decltype(boundary)>>,           \
163*6777b538SAndroid Build Coastguard Worker                   "|boundary| should not be an enum type!");                   \
164*6777b538SAndroid Build Coastguard Worker     class ScaledLinearHistogramInstance : public base::ScaledLinearHistogram { \
165*6777b538SAndroid Build Coastguard Worker      public:                                                                   \
166*6777b538SAndroid Build Coastguard Worker       ScaledLinearHistogramInstance()                                          \
167*6777b538SAndroid Build Coastguard Worker           : ScaledLinearHistogram(name,                                        \
168*6777b538SAndroid Build Coastguard Worker                                   1,                                           \
169*6777b538SAndroid Build Coastguard Worker                                   boundary,                                    \
170*6777b538SAndroid Build Coastguard Worker                                   boundary + 1,                                \
171*6777b538SAndroid Build Coastguard Worker                                   scale,                                       \
172*6777b538SAndroid Build Coastguard Worker                                   flag) {}                                     \
173*6777b538SAndroid Build Coastguard Worker     };                                                                         \
174*6777b538SAndroid Build Coastguard Worker     static base::LazyInstance<ScaledLinearHistogramInstance>::Leaky            \
175*6777b538SAndroid Build Coastguard Worker         scaled_leaky;                                                          \
176*6777b538SAndroid Build Coastguard Worker     scaled_leaky.Get().AddScaledCount(sample, count);                          \
177*6777b538SAndroid Build Coastguard Worker   } while (0)
178*6777b538SAndroid Build Coastguard Worker 
179*6777b538SAndroid Build Coastguard Worker // Helper for 'overloading' UMA_HISTOGRAM_ENUMERATION with a variable number of
180*6777b538SAndroid Build Coastguard Worker // arguments.
181*6777b538SAndroid Build Coastguard Worker #define INTERNAL_UMA_HISTOGRAM_ENUMERATION_GET_MACRO(_1, _2, NAME, ...) NAME
182*6777b538SAndroid Build Coastguard Worker 
183*6777b538SAndroid Build Coastguard Worker #define INTERNAL_UMA_HISTOGRAM_ENUMERATION_DEDUCE_BOUNDARY(name, sample,       \
184*6777b538SAndroid Build Coastguard Worker                                                            flags)              \
185*6777b538SAndroid Build Coastguard Worker   INTERNAL_HISTOGRAM_ENUMERATION_WITH_FLAG(                                    \
186*6777b538SAndroid Build Coastguard Worker       name, sample,                                                            \
187*6777b538SAndroid Build Coastguard Worker       base::internal::EnumSizeTraits<std::decay_t<decltype(sample)>>::Count(), \
188*6777b538SAndroid Build Coastguard Worker       flags)
189*6777b538SAndroid Build Coastguard Worker 
190*6777b538SAndroid Build Coastguard Worker // Note: The value in |sample| must be strictly less than |enum_size|.
191*6777b538SAndroid Build Coastguard Worker #define INTERNAL_UMA_HISTOGRAM_ENUMERATION_SPECIFY_BOUNDARY(name, sample,     \
192*6777b538SAndroid Build Coastguard Worker                                                             enum_size, flags) \
193*6777b538SAndroid Build Coastguard Worker   INTERNAL_HISTOGRAM_ENUMERATION_WITH_FLAG(name, sample, enum_size, flags)
194*6777b538SAndroid Build Coastguard Worker 
195*6777b538SAndroid Build Coastguard Worker // Similar to the previous macro but intended for enumerations. This delegates
196*6777b538SAndroid Build Coastguard Worker // the work to the previous macro, but supports scoped enumerations as well by
197*6777b538SAndroid Build Coastguard Worker // forcing an explicit cast to the HistogramBase::Sample integral type.
198*6777b538SAndroid Build Coastguard Worker //
199*6777b538SAndroid Build Coastguard Worker // Note the range checks verify two separate issues:
200*6777b538SAndroid Build Coastguard Worker // - that the declared enum size isn't out of range of HistogramBase::Sample
201*6777b538SAndroid Build Coastguard Worker // - that the declared enum size is > 0
202*6777b538SAndroid Build Coastguard Worker //
203*6777b538SAndroid Build Coastguard Worker // TODO(dcheng): This should assert that the passed in types are actually enum
204*6777b538SAndroid Build Coastguard Worker // types.
205*6777b538SAndroid Build Coastguard Worker #define INTERNAL_HISTOGRAM_ENUMERATION_WITH_FLAG(name, sample, boundary, flag) \
206*6777b538SAndroid Build Coastguard Worker   do {                                                                         \
207*6777b538SAndroid Build Coastguard Worker     using decayed_sample = std::decay<decltype(sample)>::type;                 \
208*6777b538SAndroid Build Coastguard Worker     using decayed_boundary = std::decay<decltype(boundary)>::type;             \
209*6777b538SAndroid Build Coastguard Worker     static_assert(                                                             \
210*6777b538SAndroid Build Coastguard Worker         !std::is_enum_v<decayed_boundary> || std::is_enum_v<decayed_sample>,   \
211*6777b538SAndroid Build Coastguard Worker         "Unexpected: |boundary| is enum, but |sample| is not.");               \
212*6777b538SAndroid Build Coastguard Worker     static_assert(!std::is_enum_v<decayed_sample> ||                           \
213*6777b538SAndroid Build Coastguard Worker                       !std::is_enum_v<decayed_boundary> ||                     \
214*6777b538SAndroid Build Coastguard Worker                       std::is_same_v<decayed_sample, decayed_boundary>,        \
215*6777b538SAndroid Build Coastguard Worker                   "|sample| and |boundary| shouldn't be of different enums");  \
216*6777b538SAndroid Build Coastguard Worker     static_assert(                                                             \
217*6777b538SAndroid Build Coastguard Worker         static_cast<uintmax_t>(boundary) <                                     \
218*6777b538SAndroid Build Coastguard Worker             static_cast<uintmax_t>(                                            \
219*6777b538SAndroid Build Coastguard Worker                 std::numeric_limits<base::HistogramBase::Sample>::max()),      \
220*6777b538SAndroid Build Coastguard Worker         "|boundary| is out of range of HistogramBase::Sample");                \
221*6777b538SAndroid Build Coastguard Worker     INTERNAL_HISTOGRAM_EXACT_LINEAR_WITH_FLAG(                                 \
222*6777b538SAndroid Build Coastguard Worker         name, static_cast<base::HistogramBase::Sample>(sample),                \
223*6777b538SAndroid Build Coastguard Worker         static_cast<base::HistogramBase::Sample>(boundary), flag);             \
224*6777b538SAndroid Build Coastguard Worker   } while (0)
225*6777b538SAndroid Build Coastguard Worker 
226*6777b538SAndroid Build Coastguard Worker #define INTERNAL_HISTOGRAM_SCALED_ENUMERATION_WITH_FLAG(name, sample, count, \
227*6777b538SAndroid Build Coastguard Worker                                                         scale, flag)         \
228*6777b538SAndroid Build Coastguard Worker   do {                                                                       \
229*6777b538SAndroid Build Coastguard Worker     using decayed_sample = std::decay<decltype(sample)>::type;               \
230*6777b538SAndroid Build Coastguard Worker     static_assert(std::is_enum_v<decayed_sample>,                            \
231*6777b538SAndroid Build Coastguard Worker                   "Unexpected: |sample| is not at enum.");                   \
232*6777b538SAndroid Build Coastguard Worker     constexpr auto boundary = base::internal::EnumSizeTraits<                \
233*6777b538SAndroid Build Coastguard Worker         std::decay_t<decltype(sample)>>::Count();                            \
234*6777b538SAndroid Build Coastguard Worker     static_assert(                                                           \
235*6777b538SAndroid Build Coastguard Worker         static_cast<uintmax_t>(boundary) <                                   \
236*6777b538SAndroid Build Coastguard Worker             static_cast<uintmax_t>(                                          \
237*6777b538SAndroid Build Coastguard Worker                 std::numeric_limits<base::HistogramBase::Sample>::max()),    \
238*6777b538SAndroid Build Coastguard Worker         "|boundary| is out of range of HistogramBase::Sample");              \
239*6777b538SAndroid Build Coastguard Worker     INTERNAL_HISTOGRAM_SCALED_EXACT_LINEAR_WITH_FLAG(                        \
240*6777b538SAndroid Build Coastguard Worker         name, static_cast<base::HistogramBase::Sample>(sample), count,       \
241*6777b538SAndroid Build Coastguard Worker         static_cast<base::HistogramBase::Sample>(boundary), scale, flag);    \
242*6777b538SAndroid Build Coastguard Worker   } while (0)
243*6777b538SAndroid Build Coastguard Worker 
244*6777b538SAndroid Build Coastguard Worker // This is a helper macro used by other macros and shouldn't be used directly.
245*6777b538SAndroid Build Coastguard Worker // This is necessary to expand __COUNTER__ to an actual value.
246*6777b538SAndroid Build Coastguard Worker #define INTERNAL_SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER(name, timing, key) \
247*6777b538SAndroid Build Coastguard Worker   INTERNAL_SCOPED_UMA_HISTOGRAM_TIMER_UNIQUE(name, timing, key)
248*6777b538SAndroid Build Coastguard Worker 
249*6777b538SAndroid Build Coastguard Worker // This is a helper macro used by other macros and shouldn't be used directly.
250*6777b538SAndroid Build Coastguard Worker #define INTERNAL_SCOPED_UMA_HISTOGRAM_TIMER_UNIQUE(name, timing, key)      \
251*6777b538SAndroid Build Coastguard Worker   class ScopedHistogramTimer##key {                                        \
252*6777b538SAndroid Build Coastguard Worker    public:                                                                 \
253*6777b538SAndroid Build Coastguard Worker     ScopedHistogramTimer##key() : constructed_(base::TimeTicks::Now()) {}  \
254*6777b538SAndroid Build Coastguard Worker     ~ScopedHistogramTimer##key() {                                         \
255*6777b538SAndroid Build Coastguard Worker       base::TimeDelta elapsed = base::TimeTicks::Now() - constructed_;     \
256*6777b538SAndroid Build Coastguard Worker       switch (timing) {                                                    \
257*6777b538SAndroid Build Coastguard Worker         case ScopedHistogramTiming::kMicrosecondTimes:                     \
258*6777b538SAndroid Build Coastguard Worker           UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(                         \
259*6777b538SAndroid Build Coastguard Worker               name, elapsed, base::Microseconds(1), base::Seconds(1), 50); \
260*6777b538SAndroid Build Coastguard Worker           break;                                                           \
261*6777b538SAndroid Build Coastguard Worker         case ScopedHistogramTiming::kMediumTimes:                          \
262*6777b538SAndroid Build Coastguard Worker           UMA_HISTOGRAM_TIMES(name, elapsed);                              \
263*6777b538SAndroid Build Coastguard Worker           break;                                                           \
264*6777b538SAndroid Build Coastguard Worker         case ScopedHistogramTiming::kLongTimes:                            \
265*6777b538SAndroid Build Coastguard Worker           UMA_HISTOGRAM_LONG_TIMES_100(name, elapsed);                     \
266*6777b538SAndroid Build Coastguard Worker           break;                                                           \
267*6777b538SAndroid Build Coastguard Worker       }                                                                    \
268*6777b538SAndroid Build Coastguard Worker     }                                                                      \
269*6777b538SAndroid Build Coastguard Worker                                                                            \
270*6777b538SAndroid Build Coastguard Worker    private:                                                                \
271*6777b538SAndroid Build Coastguard Worker     base::TimeTicks constructed_;                                          \
272*6777b538SAndroid Build Coastguard Worker   } scoped_histogram_timer_##key
273*6777b538SAndroid Build Coastguard Worker 
274*6777b538SAndroid Build Coastguard Worker #endif  // BASE_METRICS_HISTOGRAM_MACROS_INTERNAL_H_
275