10#include <initializer_list>
32 auto is_alpha = [](
const char c) {
33 return (c >=
'a' && c <=
'z') || (c >=
'A' && c <=
'Z') || c ==
'_';
35 auto is_alnum = [&](
const char c) {
return is_alpha(c) || (c >=
'0' && c <=
'9'); };
36 if (!is_alpha(
name.front())) {
39 return std::ranges::all_of(
name, is_alnum);
48 return name.size() < 2 ||
name[0] !=
'_' ||
name[1] !=
'_';
59 Labels(
const std::initializer_list<Label> init) : labels_(init) {
63 explicit Labels(std::vector<Label> labels) : labels_(std::move(labels)) {
68 void set(std::string
name, std::string value) {
69 labels_.push_back(
Label{std::move(
name), std::move(value)});
74 [[nodiscard]] std::span<const Label>
view() const noexcept {
78 [[nodiscard]]
bool empty() const noexcept {
79 return labels_.empty();
82 [[nodiscard]] std::size_t
size() const noexcept {
83 return labels_.size();
88 [[nodiscard]] std::size_t
hash() const noexcept {
90 hash_ = compute_hash();
98 std::vector<Label> combined;
99 combined.reserve(labels_.size() + other.labels_.size());
100 combined.insert(combined.end(), labels_.begin(), labels_.end());
101 combined.insert(combined.end(), other.labels_.begin(), other.labels_.end());
102 return Labels{std::move(combined)};
106 return labels_ == rhs.labels_;
111 std::ranges::stable_sort(labels_, {}, &
Label::name);
113 std::vector<Label> out;
114 out.reserve(labels_.size());
115 for (std::size_t i = 0; i < labels_.size(); ++i) {
116 const bool shadowed_by_next =
117 i + 1 < labels_.size() && labels_[i].name == labels_[i + 1].name;
118 if (!shadowed_by_next) {
119 out.push_back(std::move(labels_[i]));
122 labels_ = std::move(out);
126 [[nodiscard]] std::size_t compute_hash() const noexcept {
127 constexpr std::uint64_t fnv_offset = 1469598103934665603ULL;
128 constexpr std::uint64_t fnv_prime = 1099511628211ULL;
129 std::uint64_t h = fnv_offset;
130 auto mix = [&](
const std::string_view s) {
131 for (
const char c : s) {
132 h ^=
static_cast<std::uint8_t
>(c);
138 for (
const auto& [
name, value] : labels_) {
142 return static_cast<std::size_t
>(h);
145 std::vector<Label> labels_;
146 mutable std::size_t hash_ = 0;
147 mutable bool hash_valid_ =
false;
155struct std::hash<
prom::Labels> {
157 return labels.hash();
std::string name
Metric name (state-set label key).
Definition adapter.cpp:68
An immutable-by-convention set of labels, kept sorted by name with duplicates collapsed last-wins.
Definition labels.hpp:55
void set(std::string name, std::string value)
Insert or overwrite a label (last write wins on a repeated name).
Definition labels.hpp:68
std::size_t size() const noexcept
Definition labels.hpp:82
std::size_t hash() const noexcept
64-bit FNV-1a hash over the name\0value\0 stream; computed lazily and cached.
Definition labels.hpp:88
Labels merged_with(const Labels &other) const
Return *this overlaid with other; on a name collision other wins.
Definition labels.hpp:97
std::span< const Label > view() const noexcept
Read-only view over the sorted/deduped pairs.
Definition labels.hpp:74
bool empty() const noexcept
Definition labels.hpp:78
Labels(std::vector< Label > labels)
Definition labels.hpp:63
Labels(const std::initializer_list< Label > init)
Definition labels.hpp:59
bool operator==(const Labels &rhs) const
Definition labels.hpp:105
Definition adapter.hpp:24
constexpr bool is_valid_metric_name(std::string_view name) noexcept
A metric name is valid when it matches Prometheus's [a-zA-Z_][a-zA-Z0-9_]*.
Definition labels.hpp:28
constexpr bool is_valid_label_name(const std::string_view name) noexcept
A label name follows the metric-name charset but additionally rejects the __ prefix,...
Definition labels.hpp:44
A single name="value" label pair.
Definition labels.hpp:20
std::string value
Definition labels.hpp:22
std::string name
Definition labels.hpp:21
bool operator==(const Label &) const =default
std::size_t operator()(const prom::Labels &labels) const noexcept
Definition labels.hpp:156