1 // 2 // Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 3 // 4 // Use of this source code is governed by a BSD-style license 5 // that can be found in the LICENSE file in the root of the source 6 // tree. An additional intellectual property rights grant can be found 7 // in the file PATENTS. All contributing project authors may 8 // be found in the AUTHORS file in the root of the source tree. 9 // 10 11 #ifndef SYSTEM_WRAPPERS_INCLUDE_METRICS_H_ 12 #define SYSTEM_WRAPPERS_INCLUDE_METRICS_H_ 13 14 #include <string> 15 16 #include "common_types.h" // NOLINT(build/include) 17 #include "rtc_base/atomicops.h" 18 #include "rtc_base/checks.h" 19 20 // Macros for allowing WebRTC clients (e.g. Chrome) to gather and aggregate 21 // statistics. 22 // 23 // Histogram for counters. 24 // RTC_HISTOGRAM_COUNTS(name, sample, min, max, bucket_count); 25 // 26 // Histogram for enumerators. 27 // The boundary should be above the max enumerator sample. 28 // RTC_HISTOGRAM_ENUMERATION(name, sample, boundary); 29 // 30 // 31 // The macros use the methods HistogramFactoryGetCounts, 32 // HistogramFactoryGetEnumeration and HistogramAdd. 33 // 34 // Therefore, WebRTC clients must either: 35 // 36 // - provide implementations of 37 // Histogram* webrtc::metrics::HistogramFactoryGetCounts( 38 // const std::string& name, int sample, int min, int max, 39 // int bucket_count); 40 // Histogram* webrtc::metrics::HistogramFactoryGetEnumeration( 41 // const std::string& name, int sample, int boundary); 42 // void webrtc::metrics::HistogramAdd( 43 // Histogram* histogram_pointer, const std::string& name, int sample); 44 // 45 // - or link with the default implementations (i.e. 46 // system_wrappers:metrics_default). 47 // 48 // 49 // Example usage: 50 // 51 // RTC_HISTOGRAM_COUNTS("WebRTC.Video.NacksSent", nacks_sent, 1, 100000, 100); 52 // 53 // enum Types { 54 // kTypeX, 55 // kTypeY, 56 // kBoundary, 57 // }; 58 // 59 // RTC_HISTOGRAM_ENUMERATION("WebRTC.Types", kTypeX, kBoundary); 60 // 61 // NOTE: It is recommended to do the Chromium review for modifications to 62 // histograms.xml before new metrics are committed to WebRTC. 63 64 // Macros for adding samples to a named histogram. 65 66 // Histogram for counters (exponentially spaced buckets). 67 #define RTC_HISTOGRAM_COUNTS_100(name, sample) \ 68 RTC_HISTOGRAM_COUNTS(name, sample, 1, 100, 50) 69 70 #define RTC_HISTOGRAM_COUNTS_200(name, sample) \ 71 RTC_HISTOGRAM_COUNTS(name, sample, 1, 200, 50) 72 73 #define RTC_HISTOGRAM_COUNTS_500(name, sample) \ 74 RTC_HISTOGRAM_COUNTS(name, sample, 1, 500, 50) 75 76 #define RTC_HISTOGRAM_COUNTS_1000(name, sample) \ 77 RTC_HISTOGRAM_COUNTS(name, sample, 1, 1000, 50) 78 79 #define RTC_HISTOGRAM_COUNTS_10000(name, sample) \ 80 RTC_HISTOGRAM_COUNTS(name, sample, 1, 10000, 50) 81 82 #define RTC_HISTOGRAM_COUNTS_100000(name, sample) \ 83 RTC_HISTOGRAM_COUNTS(name, sample, 1, 100000, 50) 84 85 #define RTC_HISTOGRAM_COUNTS(name, sample, min, max, bucket_count) \ 86 RTC_HISTOGRAM_COMMON_BLOCK(name, sample, \ 87 webrtc::metrics::HistogramFactoryGetCounts( \ 88 name, min, max, bucket_count)) 89 90 #define RTC_HISTOGRAM_COUNTS_LINEAR(name, sample, min, max, bucket_count) \ 91 RTC_HISTOGRAM_COMMON_BLOCK(name, sample, \ 92 webrtc::metrics::HistogramFactoryGetCountsLinear( \ 93 name, min, max, bucket_count)) 94 95 // Slow metrics: pointer to metric is acquired at each call and is not cached. 96 // 97 #define RTC_HISTOGRAM_COUNTS_SPARSE_100(name, sample) \ 98 RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 100, 50) 99 100 #define RTC_HISTOGRAM_COUNTS_SPARSE_200(name, sample) \ 101 RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 200, 50) 102 103 #define RTC_HISTOGRAM_COUNTS_SPARSE_500(name, sample) \ 104 RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 500, 50) 105 106 #define RTC_HISTOGRAM_COUNTS_SPARSE_1000(name, sample) \ 107 RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 1000, 50) 108 109 #define RTC_HISTOGRAM_COUNTS_SPARSE_10000(name, sample) \ 110 RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 10000, 50) 111 112 #define RTC_HISTOGRAM_COUNTS_SPARSE_100000(name, sample) \ 113 RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 100000, 50) 114 115 #define RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, min, max, bucket_count) \ 116 RTC_HISTOGRAM_COMMON_BLOCK_SLOW(name, sample, \ 117 webrtc::metrics::HistogramFactoryGetCounts( \ 118 name, min, max, bucket_count)) 119 120 // Histogram for percentage (evenly spaced buckets). 121 #define RTC_HISTOGRAM_PERCENTAGE_SPARSE(name, sample) \ 122 RTC_HISTOGRAM_ENUMERATION_SPARSE(name, sample, 101) 123 124 // Histogram for booleans. 125 #define RTC_HISTOGRAM_BOOLEAN_SPARSE(name, sample) \ 126 RTC_HISTOGRAM_ENUMERATION_SPARSE(name, sample, 2) 127 128 // Histogram for enumerators (evenly spaced buckets). 129 // |boundary| should be above the max enumerator sample. 130 #define RTC_HISTOGRAM_ENUMERATION_SPARSE(name, sample, boundary) \ 131 RTC_HISTOGRAM_COMMON_BLOCK_SLOW( \ 132 name, sample, \ 133 webrtc::metrics::HistogramFactoryGetEnumeration(name, boundary)) 134 135 // Histogram for percentage (evenly spaced buckets). 136 #define RTC_HISTOGRAM_PERCENTAGE(name, sample) \ 137 RTC_HISTOGRAM_ENUMERATION(name, sample, 101) 138 139 // Histogram for booleans. 140 #define RTC_HISTOGRAM_BOOLEAN(name, sample) \ 141 RTC_HISTOGRAM_ENUMERATION(name, sample, 2) 142 143 // Histogram for enumerators (evenly spaced buckets). 144 // |boundary| should be above the max enumerator sample. 145 #define RTC_HISTOGRAM_ENUMERATION(name, sample, boundary) \ 146 RTC_HISTOGRAM_COMMON_BLOCK( \ 147 name, sample, \ 148 webrtc::metrics::HistogramFactoryGetEnumeration(name, boundary)) 149 150 // The name of the histogram should not vary. 151 // TODO(asapersson): Consider changing string to const char*. 152 #define RTC_HISTOGRAM_COMMON_BLOCK(constant_name, sample, \ 153 factory_get_invocation) \ 154 do { \ 155 static webrtc::metrics::Histogram* atomic_histogram_pointer = nullptr; \ 156 webrtc::metrics::Histogram* histogram_pointer = \ 157 rtc::AtomicOps::AcquireLoadPtr(&atomic_histogram_pointer); \ 158 if (!histogram_pointer) { \ 159 histogram_pointer = factory_get_invocation; \ 160 webrtc::metrics::Histogram* prev_pointer = \ 161 rtc::AtomicOps::CompareAndSwapPtr( \ 162 &atomic_histogram_pointer, \ 163 static_cast<webrtc::metrics::Histogram*>(nullptr), \ 164 histogram_pointer); \ 165 RTC_DCHECK(prev_pointer == nullptr || \ 166 prev_pointer == histogram_pointer); \ 167 } \ 168 if (histogram_pointer) { \ 169 webrtc::metrics::HistogramAdd(histogram_pointer, sample); \ 170 } \ 171 } while (0) 172 173 // Deprecated. 174 // The histogram is constructed/found for each call. 175 // May be used for histograms with infrequent updates.` 176 #define RTC_HISTOGRAM_COMMON_BLOCK_SLOW(name, sample, factory_get_invocation) \ 177 do { \ 178 webrtc::metrics::Histogram* histogram_pointer = factory_get_invocation; \ 179 if (histogram_pointer) { \ 180 webrtc::metrics::HistogramAdd(histogram_pointer, sample); \ 181 } \ 182 } while (0) 183 184 // Helper macros. 185 // Macros for calling a histogram with varying name (e.g. when using a metric 186 // in different modes such as real-time vs screenshare). Fast, because pointer 187 // is cached. |index| should be different for different names. Allowed |index| 188 // values are 0, 1, and 2. 189 #define RTC_HISTOGRAMS_COUNTS_100(index, name, sample) \ 190 RTC_HISTOGRAMS_COMMON(index, name, sample, \ 191 RTC_HISTOGRAM_COUNTS(name, sample, 1, 100, 50)) 192 193 #define RTC_HISTOGRAMS_COUNTS_200(index, name, sample) \ 194 RTC_HISTOGRAMS_COMMON(index, name, sample, \ 195 RTC_HISTOGRAM_COUNTS(name, sample, 1, 200, 50)) 196 197 #define RTC_HISTOGRAMS_COUNTS_500(index, name, sample) \ 198 RTC_HISTOGRAMS_COMMON(index, name, sample, \ 199 RTC_HISTOGRAM_COUNTS(name, sample, 1, 500, 50)) 200 201 #define RTC_HISTOGRAMS_COUNTS_1000(index, name, sample) \ 202 RTC_HISTOGRAMS_COMMON(index, name, sample, \ 203 RTC_HISTOGRAM_COUNTS(name, sample, 1, 1000, 50)) 204 205 #define RTC_HISTOGRAMS_COUNTS_10000(index, name, sample) \ 206 RTC_HISTOGRAMS_COMMON(index, name, sample, \ 207 RTC_HISTOGRAM_COUNTS(name, sample, 1, 10000, 50)) 208 209 #define RTC_HISTOGRAMS_COUNTS_100000(index, name, sample) \ 210 RTC_HISTOGRAMS_COMMON(index, name, sample, \ 211 RTC_HISTOGRAM_COUNTS(name, sample, 1, 100000, 50)) 212 213 #define RTC_HISTOGRAMS_ENUMERATION(index, name, sample, boundary) \ 214 RTC_HISTOGRAMS_COMMON(index, name, sample, \ 215 RTC_HISTOGRAM_ENUMERATION(name, sample, boundary)) 216 217 #define RTC_HISTOGRAMS_PERCENTAGE(index, name, sample) \ 218 RTC_HISTOGRAMS_COMMON(index, name, sample, \ 219 RTC_HISTOGRAM_PERCENTAGE(name, sample)) 220 221 #define RTC_HISTOGRAMS_COMMON(index, name, sample, macro_invocation) \ 222 do { \ 223 switch (index) { \ 224 case 0: \ 225 macro_invocation; \ 226 break; \ 227 case 1: \ 228 macro_invocation; \ 229 break; \ 230 case 2: \ 231 macro_invocation; \ 232 break; \ 233 default: \ 234 RTC_NOTREACHED(); \ 235 } \ 236 } while (0) 237 238 namespace webrtc { 239 namespace metrics { 240 241 // Time that should have elapsed for stats that are gathered once per call. 242 enum { kMinRunTimeInSeconds = 10 }; 243 244 class Histogram; 245 246 // Functions for getting pointer to histogram (constructs or finds the named 247 // histogram). 248 249 // Get histogram for counters. 250 Histogram* HistogramFactoryGetCounts(const std::string& name, 251 int min, 252 int max, 253 int bucket_count); 254 255 // Get histogram for counters with linear bucket spacing. 256 Histogram* HistogramFactoryGetCountsLinear(const std::string& name, 257 int min, 258 int max, 259 int bucket_count); 260 261 // Get histogram for enumerators. 262 // |boundary| should be above the max enumerator sample. 263 Histogram* HistogramFactoryGetEnumeration(const std::string& name, 264 int boundary); 265 266 // Function for adding a |sample| to a histogram. 267 void HistogramAdd(Histogram* histogram_pointer, int sample); 268 269 } // namespace metrics 270 } // namespace webrtc 271 272 #endif // SYSTEM_WRAPPERS_INCLUDE_METRICS_H_ 273