static_metrics

Attribute Macro static_metrics 

Source
#[static_metrics]
Expand description

Defines a container struct of statically defined metrics.

Applied to a struct whose fields are metric handles, this generates the registration, accessors, and metadata for the whole group. It is re-exported (and intended to be used) as saluki_metrics::static_metrics.

Because it can rewrite field storage (see “Mapped metrics” below), it must appear before any #[derive(...)] on the struct.

§Fields

Every field must be typed as Counter, Gauge, or Histogram (from the metrics crate, re-exported by saluki-metrics). Each field becomes one registered metric whose name is "<prefix>_<field_name>".

§Arguments

  • prefix = <ident> (required): a bare identifier prefixed to every metric name, for example prefix = cache.
  • labels(a, b, ...) (optional): the names of labels applied to every metric in the group. The label values are supplied to the generated new() and may be of any type implementing saluki_metrics::Stringable.

§Field attributes

  • #[metric(level = info | debug | trace)] (optional, default info): the metric’s verbosity level.
  • #[metric(mapped(...))] (optional): see below.

§Generated code

For a struct Foo, this generates Foo::new(<label>, ...) -> Foo (generic over each label value’s type), a Foo::<field>(&self) -> &<Handle> accessor per metric, a Foo::<field>_name() -> &'static str helper, and a Debug implementation that prints only the struct name. Clone is not generated; derive it directly where needed.

§Mapped metrics

A field can be mapped by one or more labels whose values are supplied at emission time rather than at construction:

#[static_metrics(prefix = component, labels(component_id))]
#[derive(Clone)]
struct Metrics {
    events_sent_total: Counter,
    // one label, sourced from any `Stringable`:
    #[metric(mapped(reason))]
    events_discarded_total: Counter,
    // or pinned to a concrete type for misuse resistance (and, potentially, cheaper conversion):
    #[metric(mapped(reason: DiscardReason))]
    other_total: Counter,
}

A mapped field’s storage is rewritten to hold a concurrent map of the dynamic label values to lazily registered handles (the source keeps writing Counter/Gauge/Histogram). Its accessor accepts each label value either by value or by reference and returns an owned handle. A typed label still only accepts its concrete type (or a reference to it), so lightweight Copy values can be passed directly without borrowing:

// bare label -> generic `Stringable` parameter; typed label -> `Borrow<T>`, so `T` or `&T` are both accepted
metrics.events_discarded_total("queue_full").increment(1);
metrics.other_total(DiscardReason::QueueFull).increment(1);
metrics.other_total(&DiscardReason::QueueFull).increment(1);

Each mapped handle is registered with the fixed struct labels plus the mapped labels. One or many labels may be given, comma-separated, mixing bare and typed forms.