]> git.proxmox.com Git - ceph.git/blame - ceph/src/common/perf_counters_key.h
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / common / perf_counters_key.h
CommitLineData
1e59de90
TL
1#pragma once
2
3#include <optional>
4#include <string>
5#include <utility>
6
7namespace ceph::perf_counters {
8
9/// A key/value pair representing a perf counter label
10using 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
28template <std::size_t Count>
29std::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
34std::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.
40template <std::size_t Count>
41std::string key_insert(std::string_view key,
42 label_pair (&&labels)[Count]);
43
44/// \brief Return the counter name for a given key.
45std::string_view key_name(std::string_view key);
46
47
48/// A forward iterator over label_pairs encoded in a key
49class 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
88class 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
111label_range key_labels(std::string_view key);
112
113
114namespace detail {
115
116std::string create(std::string_view counter_name,
117 label_pair* begin, label_pair* end);
118
119std::string insert(const char* begin1, const char* end1,
120 label_pair* begin2, label_pair* end2);
121
122} // namespace detail
123
124template <std::size_t Count>
125std::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
131template <std::size_t Count>
132std::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