]> git.proxmox.com Git - ceph.git/blob - ceph/src/common/perf_counters_key.h
update ceph source to reef 18.2.0
[ceph.git] / ceph / src / common / perf_counters_key.h
1 #pragma once
2
3 #include <optional>
4 #include <string>
5 #include <utility>
6
7 namespace ceph::perf_counters {
8
9 /// A key/value pair representing a perf counter label
10 using label_pair = std::pair<std::string_view, std::string_view>;
11
12
13 /// \brief Construct a key for a perf counter and set of labels.
14 ///
15 /// Returns a string of the form "counter_name\0key1\0val1\0key2\0val2\0",
16 /// where label pairs are sorted by key with duplicates removed.
17 ///
18 /// This string representation avoids extra memory allocations associated
19 /// with map<string, string>. It also supports the hashing and comparison
20 /// operators required for use as a key in unordered and ordered containers.
21 ///
22 /// Example:
23 /// \code
24 /// std::string key = key_create("counter_name", {
25 /// {"key1", "val1"}, {"key2", "val2"}
26 /// });
27 /// \endcode
28 template <std::size_t Count>
29 std::string key_create(std::string_view counter_name,
30 label_pair (&&labels)[Count]);
31
32 /// \brief Construct a key for a perf counter without labels.
33 /// \overload
34 std::string key_create(std::string_view counter_name);
35
36 /// \brief Insert additional labels into an existing key.
37 ///
38 /// This returns a new string without modifying the input. The returned
39 /// string has labels in sorted order and no duplicate keys.
40 template <std::size_t Count>
41 std::string key_insert(std::string_view key,
42 label_pair (&&labels)[Count]);
43
44 /// \brief Return the counter name for a given key.
45 std::string_view key_name(std::string_view key);
46
47
48 /// A forward iterator over label_pairs encoded in a key
49 class label_iterator {
50 public:
51 using base_iterator = const char*;
52 using difference_type = std::ptrdiff_t;
53 using value_type = label_pair;
54 using pointer = const value_type*;
55 using reference = const value_type&;
56
57 label_iterator() = default;
58 label_iterator(base_iterator begin, base_iterator end);
59
60 label_iterator& operator++();
61 label_iterator operator++(int);
62
63 reference operator*() const { return state->label; }
64 pointer operator->() const { return &state->label; }
65
66 auto operator<=>(const label_iterator& rhs) const = default;
67
68 private:
69 struct iterator_state {
70 base_iterator pos; // end of current label
71 base_iterator end; // end of buffer
72 label_pair label; // current label
73
74 auto operator<=>(const iterator_state& rhs) const = default;
75 };
76 // an empty state represents a past-the-end iterator
77 std::optional<iterator_state> state;
78
79 // find the next two delimiters and construct the label string views
80 static void advance(std::optional<iterator_state>& s);
81
82 // try to parse the first label pair
83 static auto make_state(base_iterator begin, base_iterator end)
84 -> std::optional<iterator_state>;
85 };
86
87 /// A sorted range of label_pairs
88 class label_range {
89 std::string_view buffer;
90 public:
91 using iterator = label_iterator;
92 using const_iterator = label_iterator;
93
94 label_range(std::string_view buffer) : buffer(buffer) {}
95
96 const_iterator begin() const { return {buffer.begin(), buffer.end()}; }
97 const_iterator cbegin() const { return {buffer.begin(), buffer.end()}; }
98
99 const_iterator end() const { return {}; }
100 const_iterator cend() const { return {}; }
101 };
102
103 /// \brief Return the sorted range of label_pairs for a given key.
104 ///
105 /// Example:
106 /// \code
107 /// for (label_pair label : key_labels(key)) {
108 /// std::cout << label.first << ":" << label.second << std::endl;
109 /// }
110 /// \endcode
111 label_range key_labels(std::string_view key);
112
113
114 namespace detail {
115
116 std::string create(std::string_view counter_name,
117 label_pair* begin, label_pair* end);
118
119 std::string insert(const char* begin1, const char* end1,
120 label_pair* begin2, label_pair* end2);
121
122 } // namespace detail
123
124 template <std::size_t Count>
125 std::string key_create(std::string_view counter_name,
126 label_pair (&&labels)[Count])
127 {
128 return detail::create(counter_name, std::begin(labels), std::end(labels));
129 }
130
131 template <std::size_t Count>
132 std::string key_insert(std::string_view key,
133 label_pair (&&labels)[Count])
134 {
135 return detail::insert(key.begin(), key.end(),
136 std::begin(labels), std::end(labels));
137 }
138
139 } // namespace ceph::perf_counters