userver: userver/utils/statistics/histogram.hpp Source File
Loading...
Searching...
No Matches
histogram.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utils/statistics/histogram.hpp
4/// @brief @copybrief utils::statistics::Histogram
5
6#include <cstdint>
7#include <memory>
8
9#include <userver/utils/span.hpp>
10#include <userver/utils/statistics/fwd.hpp>
11#include <userver/utils/statistics/histogram_view.hpp>
12
13USERVER_NAMESPACE_BEGIN
14
15namespace utils::statistics {
16
17namespace impl::histogram {
18struct BoundsBlock;
19} // namespace impl::histogram
20
21/// @ingroup userver_universal
22///
23/// @brief A histogram with a dynamically-allocated array of buckets.
24///
25/// ## Histogram metrics
26///
27/// * A histogram metric is a list of counters ("buckets") with specified bounds
28/// * The implicit lowest bound is always 0
29/// * Bucket bounds must follow the ascending order
30/// * Values on the bucket borders fall into the lower bucket
31/// * Besides normal buckets, there is also a special "infinity" bucket,
32/// which contains values that are greater than the greatest bucket bound
33/// * Each individual counter has the semantics of utils::statistics::Rate
34/// * For best portability, there should be no more than 50 buckets
35///
36/// ## Histograms vs utils::statistics::Percentile
37///
38/// @see utils::statistics::Percentile is a related metric type
39///
40/// The trade-offs of histograms with `Percentile` are:
41///
42/// 1. `Percentile` metrics are fundamentally non-summable across multiple
43/// hosts. `Histogram`, on the other hand, are summable
44/// 2. A `Histogram` takes up more storage space on the statistics server,
45/// as there are typically 20-50 buckets in a `Histogram`, but only a few
46/// required percentiles in a `Percentile`
47/// 3. `Percentile` metrics have almost infinite precision, limited only
48/// by the number of allocated atomic counters. The precision of `Histogram`
49/// metrics is limited by the initially set bounds
50///
51/// ## Usage of Histogram
52///
53/// Usage example:
54/// @snippet utils/statistics/histogram_test.cpp sample
55///
56/// Contents of a Histogram are read using utils::statistics::HistogramView.
57/// This can be useful for writing custom metric serialization formats or
58/// for testing.
59///
60/// Histogram metrics can be summed using
61/// utils::statistics::HistogramAggregator.
62///
63/// Histogram can be used in utils::statistics::MetricTag:
64/// @snippet utils/statistics/histogram_test.cpp metric tag
65class Histogram final {
66public:
67 /// @brief Sets upper bounds for each non-"infinite" bucket. The lowest bound is
68 /// always 0.
69 ///
70 /// @param upper_bounds is copied inside and is not required to be kept alive after the constructor completes.
71 explicit Histogram(utils::span<const double> upper_bounds);
72
73 /// Copies an existing histogram.
74 explicit Histogram(HistogramView other);
75
76 Histogram(Histogram&&) noexcept;
77 Histogram(const Histogram&);
78 Histogram& operator=(Histogram&&) noexcept;
79 Histogram& operator=(const Histogram&);
80 ~Histogram();
81
82 /// Atomically increment the bucket corresponding to the given value.
83 void Account(double value, std::uint64_t count = 1) noexcept;
84
85 /// Atomically reset all counters to zero.
86 friend void ResetMetric(Histogram& histogram) noexcept;
87
88 /// Allows reading the histogram.
89 HistogramView GetView() const& noexcept;
90
91 /// @cond
92 // Store Histogram in a variable before taking a view on it.
93 HistogramView GetView() && noexcept = delete;
94 /// @endcond
95
96private:
97 void UpdateBounds();
98
99 std::unique_ptr<impl::histogram::Bucket[]> buckets_;
100 // B+ tree of bucket bounds for optimization of Account.
101 std::unique_ptr<impl::histogram::BoundsBlock[]> bounds_;
102 // Duplicate size here to avoid loading an extra cache line in Account.
103 std::size_t bucket_count_;
104};
105
106/// Metric serialization support for Histogram.
107void DumpMetric(Writer& writer, const Histogram& histogram);
108
109} // namespace utils::statistics
110
111USERVER_NAMESPACE_END