// // Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. // // Use of this source code is governed by a BSD-style license // that can be found in the LICENSE file in the root of the source // tree. An additional intellectual property rights grant can be found // in the file PATENTS. All contributing project authors may // be found in the AUTHORS file in the root of the source tree. //
#if RTC_METRICS_ENABLED // Macros for allowing WebRTC clients (e.g. Chrome) to gather and aggregate // statistics. // // Histogram for counters. // RTC_HISTOGRAM_COUNTS(name, sample, min, max, bucket_count); // // Histogram for enumerators. // The boundary should be above the max enumerator sample. // RTC_HISTOGRAM_ENUMERATION(name, sample, boundary); // // // The macros use the methods HistogramFactoryGetCounts, // HistogramFactoryGetEnumeration and HistogramAdd. // // By default WebRTC provides implementations of the aforementioned methods // that can be found in system_wrappers/source/metrics.cc. If clients want to // provide a custom version, they will have to: // // 1. Compile WebRTC defining the preprocessor macro // WEBRTC_EXCLUDE_METRICS_DEFAULT (if GN is used this can be achieved // by setting the GN arg rtc_exclude_metrics_default to true). // 2. Provide implementations of: // Histogram* webrtc::metrics::HistogramFactoryGetCounts( // absl::string_view name, int sample, int min, int max, // int bucket_count); // Histogram* webrtc::metrics::HistogramFactoryGetEnumeration( // absl::string_view name, int sample, int boundary); // void webrtc::metrics::HistogramAdd( // Histogram* histogram_pointer, absl::string_view name, int sample); // // Example usage: // // RTC_HISTOGRAM_COUNTS("WebRTC.Video.NacksSent", nacks_sent, 1, 100000, 100); // // enum Types { // kTypeX, // kTypeY, // kBoundary, // }; // // RTC_HISTOGRAM_ENUMERATION("WebRTC.Types", kTypeX, kBoundary); // // NOTE: It is recommended to do the Chromium review for modifications to // histograms.xml before new metrics are committed to WebRTC.
// Macros for adding samples to a named histogram.
// Slow metrics: pointer to metric is acquired at each call and is not cached. // #define RTC_HISTOGRAM_COUNTS_SPARSE_100(name, sample) \
RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 100, 50)
// Histogram for enumerators (evenly spaced buckets). // `boundary` should be above the max enumerator sample. // // TODO(qingsi): Refactor the default implementation given by RtcHistogram, // which is already sparse, and remove the boundary argument from the macro. #define RTC_HISTOGRAM_ENUMERATION_SPARSE(name, sample, boundary) \
RTC_HISTOGRAM_COMMON_BLOCK_SLOW( \
name, sample, \
webrtc::metrics::SparseHistogramFactoryGetEnumeration(name, boundary))
// Histogram for enumerators (evenly spaced buckets). // `boundary` should be above the max enumerator sample. #define RTC_HISTOGRAM_ENUMERATION(name, sample, boundary) \
RTC_HISTOGRAM_COMMON_BLOCK_SLOW( \
name, sample, \
webrtc::metrics::HistogramFactoryGetEnumeration(name, boundary))
// The name of the histogram should not vary. #define RTC_HISTOGRAM_COMMON_BLOCK(constant_name, sample, \
factory_get_invocation) \ do { \ static std::atomic<webrtc::metrics::Histogram*> atomic_histogram_pointer( \
nullptr); \
webrtc::metrics::Histogram* histogram_pointer = \
atomic_histogram_pointer.load(std::memory_order_acquire); \ if (!histogram_pointer) { \
histogram_pointer = factory_get_invocation; \
webrtc::metrics::Histogram* null_histogram = nullptr; \
atomic_histogram_pointer.compare_exchange_strong(null_histogram, \
histogram_pointer); \
} \ if (histogram_pointer) { \
webrtc::metrics::HistogramAdd(histogram_pointer, sample); \
} \
} while (0)
// The histogram is constructed/found for each call. // May be used for histograms with infrequent updates.` #define RTC_HISTOGRAM_COMMON_BLOCK_SLOW(name, sample, factory_get_invocation) \ do { \
webrtc::metrics::Histogram* histogram_pointer = factory_get_invocation; \ if (histogram_pointer) { \
webrtc::metrics::HistogramAdd(histogram_pointer, sample); \
} \
} while (0)
// Helper macros. // Macros for calling a histogram with varying name (e.g. when using a metric // in different modes such as real-time vs screenshare). Fast, because pointer // is cached. `index` should be different for different names. Allowed `index` // values are 0, 1, and 2. #define RTC_HISTOGRAMS_COUNTS_100(index, name, sample) \
RTC_HISTOGRAMS_COMMON(index, name, sample, \
RTC_HISTOGRAM_COUNTS(name, sample, 1, 100, 50))
#define RTC_HISTOGRAMS_COMMON(index, name, sample, macro_invocation) \ do { \ switch (index) { \ case 0: \
macro_invocation; \ break; \ case 1: \
macro_invocation; \ break; \ case 2: \
macro_invocation; \ break; \ default: \
RTC_DCHECK_NOTREACHED(); \
} \
} while (0)
#else
//////////////////////////////////////////////////////////////////////////////// // This section defines no-op alternatives to the metrics macros when // RTC_METRICS_ENABLED is defined.
// Time that should have elapsed for stats that are gathered once per call.
constexpr int kMinRunTimeInSeconds = 10;
class Histogram;
// Functions for getting pointer to histogram (constructs or finds the named // histogram).
// Get histogram for counters.
Histogram* HistogramFactoryGetCounts(absl::string_view name, int min, int max, int bucket_count);
// Get histogram for counters with linear bucket spacing.
Histogram* HistogramFactoryGetCountsLinear(absl::string_view name, int min, int max, int bucket_count);
// Get histogram for enumerators. // `boundary` should be above the max enumerator sample.
Histogram* HistogramFactoryGetEnumeration(absl::string_view name, int boundary);
// Get sparse histogram for enumerators. // `boundary` should be above the max enumerator sample.
Histogram* SparseHistogramFactoryGetEnumeration(absl::string_view name, int boundary);
// Function for adding a `sample` to a histogram. void HistogramAdd(Histogram* histogram_pointer, int sample);
struct SampleInfo {
SampleInfo(absl::string_view name, int min, int max, size_t bucket_count);
~SampleInfo();
// Enables collection of samples. // This method should be called before any other call into webrtc. void Enable();
// Gets histograms and clears all samples. void GetAndReset(
std::map<std::string, std::unique_ptr<SampleInfo>, rtc::AbslStringViewCmp>*
histograms);
// Functions below are mainly for testing.
// Clears all samples. void Reset();
// Returns the number of times the `sample` has been added to the histogram. int NumEvents(absl::string_view name, int sample);
// Returns the total number of added samples to the histogram. int NumSamples(absl::string_view name);
// Returns the minimum sample value (or -1 if the histogram has no samples). int MinSample(absl::string_view name);
// Returns a map with keys the samples with at least one event and values the // number of events for that sample.
std::map<int, int> Samples(absl::string_view name);