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 WEBRTC_SYSTEM_WRAPPERS_INCLUDE_METRICS_H_
12 #define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_METRICS_H_
13 
14 #include <string>
15 
16 #include "webrtc/base/atomicops.h"
17 #include "webrtc/base/checks.h"
18 #include "webrtc/common_types.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/system_wrappers.gyp: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 
62 // Macros for adding samples to a named histogram.
63 
64 // Histogram for counters (exponentially spaced buckets).
65 #define RTC_HISTOGRAM_COUNTS_100(name, sample) \
66   RTC_HISTOGRAM_COUNTS(name, sample, 1, 100, 50)
67 
68 #define RTC_HISTOGRAM_COUNTS_200(name, sample) \
69   RTC_HISTOGRAM_COUNTS(name, sample, 1, 200, 50)
70 
71 #define RTC_HISTOGRAM_COUNTS_1000(name, sample) \
72   RTC_HISTOGRAM_COUNTS(name, sample, 1, 1000, 50)
73 
74 #define RTC_HISTOGRAM_COUNTS_10000(name, sample) \
75   RTC_HISTOGRAM_COUNTS(name, sample, 1, 10000, 50)
76 
77 #define RTC_HISTOGRAM_COUNTS_100000(name, sample) \
78   RTC_HISTOGRAM_COUNTS(name, sample, 1, 100000, 50)
79 
80 #define RTC_HISTOGRAM_COUNTS(name, sample, min, max, bucket_count) \
81   RTC_HISTOGRAM_COMMON_BLOCK(name, sample, \
82       webrtc::metrics::HistogramFactoryGetCounts(name, min, max, bucket_count))
83 
84 // Deprecated.
85 // TODO(asapersson): Remove.
86 #define RTC_HISTOGRAM_COUNTS_SPARSE_100(name, sample) \
87   RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 100, 50)
88 
89 #define RTC_HISTOGRAM_COUNTS_SPARSE_200(name, sample) \
90   RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 200, 50)
91 
92 #define RTC_HISTOGRAM_COUNTS_SPARSE_1000(name, sample) \
93   RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 1000, 50)
94 
95 #define RTC_HISTOGRAM_COUNTS_SPARSE_10000(name, sample) \
96   RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 10000, 50)
97 
98 #define RTC_HISTOGRAM_COUNTS_SPARSE_100000(name, sample) \
99   RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 100000, 50)
100 
101 #define RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, min, max, bucket_count) \
102   RTC_HISTOGRAM_COMMON_BLOCK_SLOW(name, sample, \
103       webrtc::metrics::HistogramFactoryGetCounts(name, min, max, bucket_count))
104 
105 // Histogram for percentage (evenly spaced buckets).
106 #define RTC_HISTOGRAM_PERCENTAGE(name, sample) \
107   RTC_HISTOGRAM_ENUMERATION(name, sample, 101)
108 
109 // Deprecated.
110 // TODO(asapersson): Remove.
111 #define RTC_HISTOGRAM_PERCENTAGE_SPARSE(name, sample) \
112   RTC_HISTOGRAM_ENUMERATION_SPARSE(name, sample, 101)
113 
114 // Histogram for enumerators (evenly spaced buckets).
115 // |boundary| should be above the max enumerator sample.
116 #define RTC_HISTOGRAM_ENUMERATION(name, sample, boundary) \
117   RTC_HISTOGRAM_COMMON_BLOCK(name, sample, \
118       webrtc::metrics::HistogramFactoryGetEnumeration(name, boundary))
119 
120 // Deprecated.
121 // TODO(asapersson): Remove.
122 #define RTC_HISTOGRAM_ENUMERATION_SPARSE(name, sample, boundary) \
123   RTC_HISTOGRAM_COMMON_BLOCK_SLOW(name, sample, \
124       webrtc::metrics::HistogramFactoryGetEnumeration(name, boundary))
125 
126 // The name of the histogram should not vary.
127 // TODO(asapersson): Consider changing string to const char*.
128 #define RTC_HISTOGRAM_COMMON_BLOCK(constant_name, sample, \
129                                    factory_get_invocation) \
130   do { \
131     static webrtc::metrics::Histogram* atomic_histogram_pointer = nullptr; \
132     webrtc::metrics::Histogram* histogram_pointer = \
133         rtc::AtomicOps::AcquireLoadPtr(&atomic_histogram_pointer); \
134     if (!histogram_pointer) { \
135       histogram_pointer = factory_get_invocation; \
136       webrtc::metrics::Histogram* prev_pointer = \
137           rtc::AtomicOps::CompareAndSwapPtr( \
138               &atomic_histogram_pointer, \
139               static_cast<webrtc::metrics::Histogram*>(nullptr), \
140               histogram_pointer); \
141       RTC_DCHECK(prev_pointer == nullptr || \
142                  prev_pointer == histogram_pointer); \
143     } \
144     webrtc::metrics::HistogramAdd(histogram_pointer, constant_name, sample); \
145   } while (0)
146 
147 // Deprecated.
148 // The histogram is constructed/found for each call.
149 // May be used for histograms with infrequent updates.
150 #define RTC_HISTOGRAM_COMMON_BLOCK_SLOW(name, sample, factory_get_invocation) \
151   do { \
152     webrtc::metrics::Histogram* histogram_pointer = factory_get_invocation; \
153     webrtc::metrics::HistogramAdd(histogram_pointer, name, sample); \
154   } while (0)
155 
156 namespace webrtc {
157 namespace metrics {
158 
159 // Time that should have elapsed for stats that are gathered once per call.
160 enum { kMinRunTimeInSeconds = 10 };
161 
162 class Histogram;
163 
164 // Functions for getting pointer to histogram (constructs or finds the named
165 // histogram).
166 
167 // Get histogram for counters.
168 Histogram* HistogramFactoryGetCounts(
169     const std::string& name, int min, int max, int bucket_count);
170 
171 // Get histogram for enumerators.
172 // |boundary| should be above the max enumerator sample.
173 Histogram* HistogramFactoryGetEnumeration(
174     const std::string& name, int boundary);
175 
176 // Function for adding a |sample| to a histogram.
177 // |name| can be used to verify that it matches the histogram name.
178 void HistogramAdd(
179     Histogram* histogram_pointer, const std::string& name, int sample);
180 
181 }  // namespace metrics
182 }  // namespace webrtc
183 
184 #endif  // WEBRTC_SYSTEM_WRAPPERS_INCLUDE_METRICS_H_
185 
186