// Copyright 2022 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef COMPONENTS_PAGE_LOAD_METRICS_BROWSER_OBSERVERS_USE_COUNTER_AT_MOST_ONCE_ENUM_UMA_DEFERRER_H_ #define COMPONENTS_PAGE_LOAD_METRICS_BROWSER_OBSERVERS_USE_COUNTER_AT_MOST_ONCE_ENUM_UMA_DEFERRER_H_ #include <bitset> #include "base/metrics/histogram_functions.h" namespace internal { // Helper functions for AtMostOnceEnumUmaDeferrer // // These functions refers implementation details of // base/metrics/histogram.cc. Keep them synchronized with that. base::HistogramBase* GetHistogramExactLinear(const char* name, int exclusive_max); // For getting an enumerated histogram. template <typename T> base::HistogramBase* GetHistogramEnumeration(const char* name) { … } template <typename T> void UmaHistogramEnumeration(base::HistogramBase* histogram, T sample) { … } } // namespace internal // A helper to defer UMA recording for prerendered pages for a UMA. // // A UMA has some options for prerendered pages: // // - Don't record any metrics. // - Record metrics if the page is activated and discard them if cancelled. // - Record metrics unconditionally. // // The first and third options are easy. For the second option, we have to defer // recording metrics to a histogram. If only one sample per navigation is // recorded, this is done by storing a sample in observer and recording in // OnComplete. In more gerenal case, systematic deferrers help us and makes code // simple. AtMostOnceEnumUmaDeferrer provides deferring mechanism with // assumptions of UseCounterPageLoadMetricsObserver. // // This class has two states: deferred (initial) and non deferred. // In deferred state, RecordOrDefer* methods collect samples into an inner // bitset. DisableDeferAndFlush changes the state to non deferred and flush the // collected samples. In non deferred state, RecordOrDefer bypass // deferring and just record a sample. // // This class uses a bitset to ensure: // // - To record a value at most once, i.e. already recorded value is ignored. // - To reduce memory usage. template <typename T> class AtMostOnceEnumUmaDeferrer { … }; template <typename T> AtMostOnceEnumUmaDeferrer<T>::AtMostOnceEnumUmaDeferrer(const char* name) { … } template <typename T> AtMostOnceEnumUmaDeferrer<T>::~AtMostOnceEnumUmaDeferrer() = default; template <typename T> void AtMostOnceEnumUmaDeferrer<T>::DisableDeferAndFlush() { … } template <typename T> void AtMostOnceEnumUmaDeferrer<T>::RecordOrDefer(T sample) { … } template <typename T> bool AtMostOnceEnumUmaDeferrer<T>::IsRecordedOrDeferred(T sample) const { … } #endif // COMPONENTS_PAGE_LOAD_METRICS_BROWSER_OBSERVERS_USE_COUNTER_AT_MOST_ONCE_ENUM_UMA_DEFERRER_H_