userver: userver/utils/statistics/labels.hpp Source File
Loading...
Searching...
No Matches
labels.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utils/statistics/labels.hpp
4/// @brief Owning and non owning labels representations.
5
6#include <string>
7#include <string_view>
8#include <type_traits>
9
10#include <fmt/format.h>
11
12#include <userver/utils/assert.hpp>
13
14USERVER_NAMESPACE_BEGIN
15
16namespace utils::statistics {
17
18class Label;
19
20/// @ingroup userver_universal
21///
22/// @brief Non owning label name+value storage.
23class LabelView final {
24public:
25 LabelView() = delete;
26 LabelView(Label&& label) = delete;
27 explicit LabelView(const Label& label);
28 constexpr LabelView(std::string_view name, std::string_view value)
29 : name_(name),
30 value_(value)
31 {
32 UINVARIANT(!name_.empty(), "The label name must not be empty.");
33 }
34
35 template <class T>
36 requires std::is_arithmetic_v<T>
37 constexpr LabelView(std::string_view, T) {
38 static_assert(!sizeof(T), "Labels should not be arithmetic values, only strings!");
39 }
40
41 constexpr explicit operator bool() const { return !name_.empty(); }
42
43 constexpr std::string_view Name() const { return name_; }
44 constexpr std::string_view Value() const { return value_; }
45
46private:
47 std::string_view name_{};
48 std::string_view value_{};
49};
50
51bool operator<(const LabelView& x, const LabelView& y) noexcept;
52bool operator==(const LabelView& x, const LabelView& y) noexcept;
53
54/// @ingroup userver_universal
55///
56/// @brief Label name+value storage.
57class Label final {
58public:
59 Label() = default;
60 explicit Label(LabelView view);
61 Label(std::string name, std::string value);
62
63 template <class T>
64 requires std::is_arithmetic_v<T>
65 Label(std::string, T) {
66 static_assert(!sizeof(T), "Labels should not be arithmetic values, only strings!");
67 }
68
69 explicit operator bool() const { return !name_.empty(); }
70 explicit operator LabelView() const { return {name_, value_}; }
71
72 const std::string& Name() const { return name_; }
73 const std::string& Value() const& { return value_; }
74 std::string& Value() & { return value_; }
75 std::string&& Value() && { return std::move(value_); }
76
77private:
78 std::string name_;
79 std::string value_;
80};
81
82bool operator<(const Label& x, const Label& y) noexcept;
83bool operator==(const Label& x, const Label& y) noexcept;
84
85/// @ingroup userver_universal
86///
87/// @brief View over a continuous range of LabelView.
88class LabelsSpan final {
89public:
90 using iterator = const LabelView*;
91 using const_iterator = const LabelView*;
92
93 LabelsSpan() = default;
94 LabelsSpan(const LabelView* begin, const LabelView* end) noexcept;
95 LabelsSpan(std::initializer_list<LabelView> il) noexcept : LabelsSpan(il.begin(), il.end()) {}
96
97 template <class Container>
98 requires std::is_same_v<
99 decltype(*(std::declval<const Container&>().data() + std::declval<const Container&>().size())),
100 const LabelView&>
101 /*implicit*/ LabelsSpan(const Container& cont) noexcept : LabelsSpan(cont.data(), cont.data() + cont.size()) {}
102
103 const LabelView* begin() const noexcept { return begin_; }
104 const LabelView* end() const noexcept { return end_; }
105 std::size_t size() const noexcept { return end_ - begin_; }
106 bool empty() const noexcept { return end_ == begin_; }
107
108private:
109 const LabelView* begin_{nullptr};
110 const LabelView* end_{nullptr};
111};
112
113} // namespace utils::statistics
114
115USERVER_NAMESPACE_END
116
117template <>
118struct fmt::formatter<USERVER_NAMESPACE::utils::statistics::LabelView> {
119 constexpr static auto parse(format_parse_context& ctx) { return ctx.begin(); }
120
121 template <typename FormatContext>
122 auto format(USERVER_NAMESPACE::utils::statistics::LabelView value, FormatContext& ctx) const {
123 return fmt::format_to(ctx.out(), "{}={}", value.Name(), value.Value());
124 }
125};
126
127template <>
128struct fmt::formatter<USERVER_NAMESPACE::utils::statistics::Label>
129 : public fmt::formatter<USERVER_NAMESPACE::utils::statistics::LabelView> {
130 template <typename FormatContext>
131 auto format(const USERVER_NAMESPACE::utils::statistics::Label& value, FormatContext& ctx) const {
132 return formatter<USERVER_NAMESPACE::utils::statistics::LabelView>::format(
133 USERVER_NAMESPACE::utils::statistics::LabelView{value},
134 ctx
135 );
136 }
137};
138
139template <>
140struct fmt::formatter<USERVER_NAMESPACE::utils::statistics::LabelsSpan> {
141 constexpr static auto parse(format_parse_context& ctx) { return ctx.begin(); }
142
143 fmt::format_context::iterator format(
144 USERVER_NAMESPACE::utils::statistics::LabelsSpan value,
145 fmt::format_context& ctx
146 ) const;
147};