32#include <logman/logman.hpp>
61 [[nodiscard]]
virtual std::uint64_t
version() const noexcept = 0;
63 [[nodiscard]] virtual std::
string full_name(std::string_view base) const = 0;
67 [[nodiscard]] virtual comms::DisplayInfo
73 [[nodiscard]] virtual
bool decorates() const noexcept = 0;
80[[nodiscard]]
inline comms::DisplayInfo
merge_display(
const comms::DisplayInfo& base,
81 const comms::DisplayInfo& over) {
82 comms::DisplayInfo out = base;
86 if (over.description) {
87 out.description = over.description;
93 out.color = over.color;
99[[nodiscard]]
inline bool display_empty(
const comms::DisplayInfo& display)
noexcept {
100 return !display.name && !display.description && !display.icon && !display.color;
121 comms::DisplayInfo display,
122 std::shared_ptr<ScopeState> parent =
nullptr)
123 : prefix_(std::move(prefix)), const_labels_(std::move(const_labels)),
124 display_(std::move(display)), parent_(std::move(parent)) {}
126 [[nodiscard]] std::uint64_t
version() const noexcept
override {
127 const std::uint64_t self = version_.load(std::memory_order_acquire);
128 return parent_ ? self + parent_->version() : self;
130 [[nodiscard]] std::string
full_name(
const std::string_view base)
const override {
133 const std::scoped_lock lock(mutex_);
134 out = prefix_ + std::string(base);
136 return parent_ ? parent_->full_name(out) : out;
141 const std::scoped_lock lock(mutex_);
144 return parent_ ? parent_->effective_labels(merged) : merged;
146 [[nodiscard]] comms::DisplayInfo
148 comms::DisplayInfo merged;
150 const std::scoped_lock lock(mutex_);
153 return parent_ ? parent_->effective_display(merged) : merged;
155 [[nodiscard]]
bool decorates() const noexcept
override {
157 const std::scoped_lock lock(mutex_);
158 if (!prefix_.empty() || !const_labels_.empty() || !
display_empty(display_)) {
162 return parent_ && parent_->decorates();
165 [[nodiscard]] std::string
prefix()
const {
166 const std::scoped_lock lock(mutex_);
171 const std::scoped_lock lock(mutex_);
172 prefix_ = std::move(prefix);
177 const std::scoped_lock lock(mutex_);
178 return const_labels_;
182 const std::scoped_lock lock(mutex_);
183 const_labels_ = std::move(labels);
189 const std::scoped_lock lock(mutex_);
190 const_labels_.set(std::move(
name), std::move(value));
194 [[nodiscard]] comms::DisplayInfo
display()
const {
195 const std::scoped_lock lock(mutex_);
200 const std::scoped_lock lock(mutex_);
201 display_ = std::move(display);
210 const std::scoped_lock lock(mutex_);
211 prefix_ = std::move(prefix);
212 const_labels_ = std::move(const_labels);
213 display_ = std::move(display);
219 void bump() noexcept {
220 version_.fetch_add(1, std::memory_order_release);
223 mutable std::mutex mutex_;
226 comms::DisplayInfo display_;
229 std::shared_ptr<ScopeState> parent_;
230 std::atomic<std::uint64_t> version_{1};
239 static auto decoration = std::make_shared<DecorationState>();
253class AtomicSharedPtr {
255 AtomicSharedPtr() =
default;
257 [[nodiscard]] std::shared_ptr<const T> load() const noexcept {
258#if defined(__cpp_lib_atomic_shared_ptr)
259 return value_.load(std::memory_order_acquire);
261 const std::scoped_lock lock(mutex_);
266 void store(std::shared_ptr<const T> desired)
noexcept {
267#if defined(__cpp_lib_atomic_shared_ptr)
268 value_.store(std::move(desired), std::memory_order_release);
270 const std::scoped_lock lock(mutex_);
271 value_ = std::move(desired);
276#if defined(__cpp_lib_atomic_shared_ptr)
277 std::atomic<std::shared_ptr<const T>> value_;
279 mutable std::mutex mutex_;
280 std::shared_ptr<const T> value_;
312 std::uint64_t adapter_version = 0;
313 std::uint64_t scope_version = 0;
315 detail::AtomicSharedPtr<Bound>
bound;
341 bool has_unit =
false;
342 bool unit_from_dimval =
false;
352 return Unit{unit_name, unit_kind, unit_symbol, unit_from_dimval};
363 meta.
unit = unit_view();
376template <
class Derived>
380 [[nodiscard]] std::string_view
name() const noexcept {
398 core_->name = std::string(
name);
399 core_->base_name = std::string(
name);
400 core_->help = std::string(help);
401 core_->source = detail::global_adapter_cell();
402 core_->scope = detail::global_decoration();
406 explicit MetricBase(std::shared_ptr<MetricCore> core) : core_(std::move(core)) {}
436 if (
const auto b = core_->bound.load()) {
440 const std::uint64_t av = core_->source->version();
441 if (
const std::uint64_t sv = core_->scope ? core_->scope->version() : 0;
442 b->adapter_version == av && b->scope_version == sv) {
449 [[nodiscard]]
const std::shared_ptr<MetricCore>&
core() const noexcept {
460 auto child = std::make_shared<MetricCore>();
461 child->type = core_->type;
462 child->name = core_->name;
463 child->source = core_->source;
464 child->pinned =
true;
465 child->family = family_core();
466 child->bound.store(std::make_shared<const MetricCore::Bound>(
468 return Derived{std::move(child)};
476 if (observed.empty()) {
479 const std::shared_ptr<MetricCore> fam = family_core();
480 const std::scoped_lock lock(fam->unit_mutex);
481 if (!fam->has_unit) {
482 fam->unit_name = std::string(observed.name);
483 fam->unit_kind = std::string(observed.kind);
484 fam->unit_symbol = std::string(observed.symbol);
485 fam->unit_from_dimval = observed.from_dimval;
486 fam->has_unit =
true;
488 if (
const auto fb = fam->bound.load()) {
492 if (
const auto cb = core_->bound.load()) {
496 adapter.set_unit(handle, fam->unit_view());
499 if (!fam->unit_kind.empty() && !observed.kind.empty() && fam->unit_kind != observed.kind) {
500 if (
auto* lg = logger()) {
501 lg->warn(
"metric '{}' dropping sample: unit kind '{}' does not match "
514 [[nodiscard]]
bool check_finite(
const double value, std::string_view op)
const noexcept {
515 if (std::isnan(value) || std::isinf(value)) {
516 if (
auto* lg = logger()) {
517 lg->warn(
"metric '{}' dropping {}: non-finite value", core_->name, op);
525 [[nodiscard]]
static spdlog::logger*
logger() noexcept {
526 static std::shared_ptr<spdlog::logger> lg = logman::get(
"prom");
533 [[nodiscard]] std::shared_ptr<MetricCore> family_core() const noexcept {
534 return core_->family ? core_->family : core_;
541 [[nodiscard]] Binding rebind() const noexcept {
542 const std::scoped_lock lock(core_->bind_mutex);
543 const std::uint64_t av = core_->source->version();
544 const std::uint64_t sv = core_->scope ? core_->scope->version() : 0;
545 if (
const auto b = core_->bound.load()) {
546 if (core_->pinned || (b->adapter_version == av && b->scope_version == sv)) {
547 return Binding{b->adapter, b->handle};
550 const AdapterPtr adapter = core_->source->adapter();
552 core_->name = core_->scope->full_name(core_->base_name);
553 core_->const_labels = core_->scope->effective_labels(core_->base_labels);
554 core_->display = core_->scope->effective_display(core_->base_display);
556 const MetricHandle handle = adapter->register_metric(core_->build_meta());
558 std::make_shared<const MetricCore::Bound>(MetricCore::Bound{adapter, handle, av, sv}));
559 return Binding{adapter, handle};
::prometheus::Histogram::BucketBoundaries buckets
Definition adapter.cpp:65
std::string name
Metric name (state-set label key).
Definition adapter.cpp:68
::prometheus::Summary::Quantiles quantiles
Definition adapter.cpp:66
prom::MetricType type
Definition adapter.cpp:53
The pluggable backend.
Definition adapter.hpp:62
An immutable-by-convention set of labels, kept sorted by name with duplicates collapsed last-wins.
Definition labels.hpp:55
Labels merged_with(const Labels &other) const
Return *this overlaid with other; on a name collision other wins.
Definition labels.hpp:97
CRTP base shared by every metric type.
Definition metric_base.hpp:377
MetricBase(MetricBase &&)=default
MetricBase & operator=(const MetricBase &)=default
MetricType type() const noexcept
The metric kind.
Definition metric_base.hpp:385
Derived make_child(const Labels &dynamic) const noexcept
Resolve a labeled child of the same metric type.
Definition metric_base.hpp:458
bool reconcile_unit(const Unit &observed, Adapter &adapter) const noexcept
Reconcile an observed unit against the family's known unit.
Definition metric_base.hpp:475
static spdlog::logger * logger() noexcept
The shared per-process metrics logger.
Definition metric_base.hpp:525
MetricBase(const MetricType type, const std::string_view name, const std::string_view help)
Standalone, unbound construction from a name and help string.
Definition metric_base.hpp:395
std::string_view name() const noexcept
The metric's fully-qualified name.
Definition metric_base.hpp:380
const std::shared_ptr< MetricCore > & core() const noexcept
Definition metric_base.hpp:449
MetricBase(const MetricBase &)=default
MetricBase(std::shared_ptr< MetricCore > core)
Adopt an already-populated core (registered metrics and children).
Definition metric_base.hpp:406
bool check_finite(const double value, std::string_view op) const noexcept
Drop-and-log guard for a non-finite sample.
Definition metric_base.hpp:514
MetricBase & operator=(MetricBase &&)=default
std::shared_ptr< MetricCore > core_
Definition metric_base.hpp:530
Binding bind() const noexcept
Resolve the adapter and backend handle this metric should record against.
Definition metric_base.hpp:435
Read-only view a scoped metric uses to re-resolve its name, constant labels, and display metadata aga...
Definition metric_base.hpp:51
virtual std::string full_name(std::string_view base) const =0
The effective metric name for a base (un-prefixed) name.
ScopeState & operator=(const ScopeState &)=delete
virtual comms::DisplayInfo effective_display(const comms::DisplayInfo &own) const =0
The effective display metadata for a metric's own display.
virtual ~ScopeState()=default
ScopeState(const ScopeState &)=delete
virtual std::uint64_t version() const noexcept=0
Monotonic counter, bumped on every configuration change.
ScopeState(ScopeState &&)=delete
virtual bool decorates() const noexcept=0
Whether this decoration actually changes anything (a non-empty prefix, constant labels,...
virtual Labels effective_labels(const Labels &own) const =0
The effective constant labels for a metric's own labels.
ScopeState & operator=(ScopeState &&)=delete
A live, thread-safe metric decoration — a name prefix, default constant labels, and default display m...
Definition metric_base.hpp:116
comms::DisplayInfo display() const
Definition metric_base.hpp:194
Labels effective_labels(const Labels &own) const override
The effective constant labels for a metric's own labels.
Definition metric_base.hpp:138
Labels const_labels() const
Definition metric_base.hpp:176
std::uint64_t version() const noexcept override
Monotonic counter, bumped on every configuration change.
Definition metric_base.hpp:126
bool decorates() const noexcept override
Whether this decoration actually changes anything (a non-empty prefix, constant labels,...
Definition metric_base.hpp:155
DecorationState()=default
void set_prefix(std::string prefix)
Definition metric_base.hpp:169
void set_const_labels(Labels labels)
Definition metric_base.hpp:180
comms::DisplayInfo effective_display(const comms::DisplayInfo &own) const override
The effective display metadata for a metric's own display.
Definition metric_base.hpp:147
void set_display(comms::DisplayInfo display)
Definition metric_base.hpp:198
DecorationState(std::string prefix, Labels const_labels, comms::DisplayInfo display, std::shared_ptr< ScopeState > parent=nullptr)
Definition metric_base.hpp:119
void add_const_label(std::string name, std::string value)
Definition metric_base.hpp:187
void configure(std::string prefix, Labels const_labels, comms::DisplayInfo display)
Replace prefix, constant labels, and display in one shot (single version bump).
Definition metric_base.hpp:208
std::string prefix() const
Definition metric_base.hpp:165
std::string full_name(const std::string_view base) const override
The effective metric name for a base (un-prefixed) name.
Definition metric_base.hpp:130
Structural bridge to dimval: the DimensionalValue concept, NormalizedValue, and the normalize() overl...
The process-wide adapter cell and its install/swap semantics.
The backend boundary: MetricMeta, MetricState/MetricHandle, and the pure-virtual Adapter interface.
Label vocabulary: Label, the sorted/deduped Labels set, name validation, and an std::hash<Labels> spe...
comms::DisplayInfo merge_display(const comms::DisplayInfo &base, const comms::DisplayInfo &over)
Overlay a metric's own display fields onto a set of defaults; each per-metric field that is set wins ...
Definition metric_base.hpp:80
bool display_empty(const comms::DisplayInfo &display) noexcept
Whether a DisplayInfo carries any field at all.
Definition metric_base.hpp:99
std::shared_ptr< DecorationState > global_decoration()
The process-wide decoration shared by Registry::global(), every standalone metric,...
Definition metric_base.hpp:238
Definition adapter.hpp:24
MetricType
The OpenMetrics / Prometheus metric kinds prom understands.
Definition unit.hpp:15
std::shared_ptr< Adapter > AdapterPtr
Shared ownership of an Adapter.
Definition fwd.hpp:38
std::shared_ptr< MetricState > MetricHandle
Opaque, backend-owned handle to a registered metric family or a labeled child series.
Definition fwd.hpp:34
A resolved (adapter, handle) snapshot — the result of bind().
Definition metric_base.hpp:417
MetricHandle handle
Definition metric_base.hpp:419
AdapterPtr adapter
Definition metric_base.hpp:418
Definition metric_base.hpp:309
MetricHandle handle
Definition metric_base.hpp:311
AdapterPtr adapter
Definition metric_base.hpp:310
Shared, reference-counted state behind every metric handle.
Definition metric_base.hpp:289
MetricMeta build_meta() const
Assemble the transient registration metadata.
Definition metric_base.hpp:358
std::mutex bind_mutex
Definition metric_base.hpp:330
std::mutex unit_mutex
Definition metric_base.hpp:340
std::string unit_name
Definition metric_base.hpp:343
std::string unit_symbol
Definition metric_base.hpp:345
Unit unit_view() const
Build a non-owning view of the currently-known unit.
Definition metric_base.hpp:348
std::string help
Definition metric_base.hpp:294
std::shared_ptr< MetricCore > family
Definition metric_base.hpp:335
std::vector< double > buckets
Definition metric_base.hpp:297
std::string base_name
Definition metric_base.hpp:327
comms::DisplayInfo base_display
Definition metric_base.hpp:329
detail::AtomicSharedPtr< Bound > bound
Definition metric_base.hpp:315
Labels base_labels
Definition metric_base.hpp:328
Labels const_labels
Definition metric_base.hpp:295
std::string name
Definition metric_base.hpp:293
std::shared_ptr< AdapterSource > source
Definition metric_base.hpp:303
comms::DisplayInfo display
Definition metric_base.hpp:296
std::vector< double > quantiles
Definition metric_base.hpp:298
std::string unit_kind
Definition metric_base.hpp:344
std::shared_ptr< ScopeState > scope
Definition metric_base.hpp:326
std::vector< std::string > states
Definition metric_base.hpp:299
OpenMetrics unit suffix plus optional dimensional metadata.
Definition unit.hpp:53
Metric kinds (MetricType) and the OpenMetrics Unit descriptor.