40 typename std::remove_cvref_t<T>::ValueType;
42 { t.observe(
typename std::remove_cvref_t<T>::ValueType{1}) } -> std::same_as<void>;
43 { t.setBuckets(std::vector<
typename std::remove_cvref_t<T>::ValueType>{}) } -> std::same_as<void>;
44 { t.serializeValue(std::string{}, std::string{}, std::declval<OStream&>()) } -> std::same_as<void>;
50 using ValueType = NumberType;
63 setBuckets(std::vector<ValueType>
const& bounds)
65 auto data = data_->template lock<std::scoped_lock>();
66 ASSERT(
data->buckets.empty(),
"Buckets can be set only once.");
67 data->buckets.reserve(bounds.size());
68 for (
auto const& bound : bounds) {
69 data->buckets.emplace_back(bound);
74 observe(ValueType
const value)
76 auto data = data_->template lock<std::scoped_lock>();
77 auto const bucket = std::lower_bound(
78 data->buckets.begin(),
data->buckets.end(), value, [](Bucket
const& bucket, ValueType
const& value) {
79 return bucket.upperBound < value;
82 if (bucket !=
data->buckets.end()) {
85 ++
data->lastBucket.count;
91 serializeValue(std::string
const& name, std::string labelsString,
OStream& stream)
const
93 if (labelsString.empty()) {
97 labelsString.front() ==
'{' && labelsString.back() ==
'}',
98 "Labels must be in Prometheus serialized format."
100 labelsString.back() =
',';
103 auto data = data_->template lock<std::scoped_lock>();
104 std::uint64_t cumulativeCount = 0;
106 for (
auto const& bucket :
data->buckets) {
107 cumulativeCount += bucket.count;
108 stream << name <<
"_bucket" << labelsString <<
"le=\"" << bucket.upperBound <<
"\"} " << cumulativeCount
111 cumulativeCount +=
data->lastBucket.count;
112 stream << name <<
"_bucket" << labelsString <<
"le=\"+Inf\"} " << cumulativeCount <<
'\n';
114 if (labelsString.size() == 1) {
117 labelsString.back() =
'}';
119 stream << name <<
"_sum" << labelsString <<
" " <<
data->sum <<
'\n';
120 stream << name <<
"_count" << labelsString <<
" " << cumulativeCount <<
'\n';
125 Bucket(ValueType upperBound) : upperBound(upperBound)
129 ValueType upperBound;
130 std::uint64_t count = 0;
134 std::vector<Bucket> buckets;
135 Bucket lastBucket{std::numeric_limits<ValueType>::max()};
138 std::unique_ptr<util::Mutex<Data>> data_ = std::make_unique<util::Mutex<Data>>();