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