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(),
81 [](Bucket
const& bucket, ValueType
const& value) { return bucket.upperBound < value; }
83 if (bucket !=
data->buckets.end()) {
86 ++
data->lastBucket.count;
92 serializeValue(std::string
const& name, std::string labelsString,
OStream& stream)
const
94 if (labelsString.empty()) {
98 labelsString.front() ==
'{' && labelsString.back() ==
'}',
99 "Labels must be in Prometheus serialized format."
101 labelsString.back() =
',';
104 auto data = data_->template lock<std::scoped_lock>();
105 std::uint64_t cumulativeCount = 0;
107 for (
auto const& bucket :
data->buckets) {
108 cumulativeCount += bucket.count;
109 stream << name <<
"_bucket" << labelsString <<
"le=\"" << bucket.upperBound <<
"\"} " << cumulativeCount
112 cumulativeCount +=
data->lastBucket.count;
113 stream << name <<
"_bucket" << labelsString <<
"le=\"+Inf\"} " << cumulativeCount <<
'\n';
115 if (labelsString.size() == 1) {
118 labelsString.back() =
'}';
120 stream << name <<
"_sum" << labelsString <<
" " <<
data->sum <<
'\n';
121 stream << name <<
"_count" << labelsString <<
" " << cumulativeCount <<
'\n';
126 Bucket(ValueType upperBound) : upperBound(upperBound)
130 ValueType upperBound;
131 std::uint64_t count = 0;
135 std::vector<Bucket> buckets;
136 Bucket lastBucket{std::numeric_limits<ValueType>::max()};
139 std::unique_ptr<util::Mutex<Data>> data_ = std::make_unique<util::Mutex<Data>>();