userver: userver/utils/statistics/storage.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
storage.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utils/statistics/storage.hpp
4/// @brief @copybrief utils::statistics::Storage
5
6#include <atomic>
7#include <functional>
8#include <initializer_list>
9#include <list>
10#include <string>
11#include <unordered_map>
12#include <variant>
13#include <vector>
14
15#include <userver/engine/shared_mutex.hpp>
16#include <userver/formats/json/value_builder.hpp>
17#include <userver/utils/assert.hpp>
18#include <userver/utils/statistics/entry.hpp>
19#include <userver/utils/statistics/metric_value.hpp>
20#include <userver/utils/statistics/writer.hpp>
21
22USERVER_NAMESPACE_BEGIN
23
24namespace utils::statistics {
25
26/// @brief Used in legacy statistics extenders
27struct StatisticsRequest final {};
28
29/// @brief Class describing the request for metrics data.
30///
31/// Metric path and metric name are the same thing. For example for code like
32///
33/// @code
34/// writer["a"]["b"]["c"] = 42;
35/// @endcode
36///
37/// the metric name is "a.b.c" and in Prometheus format it would be escaped like
38/// "a_b_c{} 42".
39///
40/// @note `add_labels` should not match labels from Storage, otherwise the
41/// returned metrics may not be read by metrics server.
42class Request final {
43 public:
44 using AddLabels = std::unordered_map<std::string, std::string>;
45
46 /// Default request without parameters. Equivalent to requesting all the
47 /// metrics without adding or requiring any labels.
48 Request() = default;
49
50 /// Makes request for metrics whose path starts with the `prefix`.
51 static Request MakeWithPrefix(const std::string& prefix,
52 AddLabels add_labels = {},
53 std::vector<Label> require_labels = {});
54
55 /// Makes request for metrics whose path is `path`.
56 static Request MakeWithPath(const std::string& path,
57 AddLabels add_labels = {},
58 std::vector<Label> require_labels = {});
59
60 /// Return metrics whose path matches with this `prefix`
61 const std::string prefix{};
62
63 /// Enum for different match types of the `prefix`
64 enum class PrefixMatch {
65 kNoop, ///< Do not match, the `prefix` is empty
66 kExact, ///< `prefix` equal to path
67 kStartsWith, ///< Metric path starts with `prefix`
68 };
69
70 /// Match type of the `prefix`
72
73 /// Require those labels in the metric
75
76 /// Add those labels to each returned metric
78
79 private:
80 Request(std::string prefix_in, PrefixMatch path_match_type_in,
81 std::vector<Label> require_labels_in, AddLabels add_labels_in);
82};
83
84using ExtenderFunc =
85 std::function<formats::json::ValueBuilder(const StatisticsRequest&)>;
86
87using WriterFunc = std::function<void(Writer&)>;
88
89namespace impl {
90
91struct MetricsSource final {
92 std::string prefix_path;
93 std::vector<std::string> path_segments;
94 ExtenderFunc extender;
95
96 WriterFunc writer;
97 std::vector<Label> writer_labels;
98};
99
100using StorageData = std::list<MetricsSource>;
101using StorageIterator = StorageData::iterator;
102
103inline constexpr bool kCheckSubscriptionUB = utils::impl::kEnableAssert;
104
105} // namespace impl
106
108 public:
109 virtual ~BaseFormatBuilder();
110
111 virtual void HandleMetric(std::string_view path, LabelsSpan labels,
112 const MetricValue& value) = 0;
113};
114
115/// @ingroup userver_clients
116///
117/// Storage of metrics, usually retrieved from components::StatisticsStorage.
118///
119/// See utils::statistics::Writer for an information on how to write metrics.
120class Storage final {
121 public:
122 Storage();
123
124 Storage(const Storage&) = delete;
125
126 /// Creates new Json::Value and calls every deprecated registered extender
127 /// func over it.
128 ///
129 /// @deprecated Use VisitMetrics instead.
130 formats::json::Value GetAsJson() const;
131
132 /// Visits all the metrics and calls `out.HandleMetric` for each metric.
133 void VisitMetrics(BaseFormatBuilder& out, const Request& request = {}) const;
134
135 /// @cond
136 /// Must be called from StatisticsStorage only. Don't call it from user
137 /// components.
138 void StopRegisteringExtenders();
139 /// @endcond
140
141 /// @brief Add a writer function. Note that `func` is called concurrently with
142 /// other code, so it should be thread\coroutine safe.
143 Entry RegisterWriter(std::string common_prefix, WriterFunc func,
144 std::vector<Label> add_labels = {});
145
146 /// @deprecated Use RegisterWriter instead.
147 Entry RegisterExtender(std::string prefix, ExtenderFunc func);
148
149 void UnregisterExtender(impl::StorageIterator iterator,
150 impl::UnregisteringKind kind) noexcept;
151
152 private:
153 Entry DoRegisterExtender(impl::MetricsSource&& source);
154
155 std::atomic<bool> may_register_extenders_;
156 impl::StorageData metrics_sources_;
157 mutable engine::SharedMutex mutex_;
158};
159
160} // namespace utils::statistics
161
162USERVER_NAMESPACE_END