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