fast_telemetry/metric/label.rs
1//! Label trait for enum-indexed metrics.
2//!
3//! Labels provide O(1) dimensional metrics without HashMap lookups.
4//! Each label enum variant maps directly to an array index.
5
6use std::fmt::Debug;
7
8/// Trait for label enums used with `LabeledCounter`, `LabeledGauge`, etc.
9///
10/// Implementing this trait allows an enum to be used as a dimension for metrics.
11/// Each variant maps to an array index, enabling O(1) metric lookup and update.
12///
13/// # Example
14///
15/// ```ignore
16/// #[derive(Copy, Clone, Debug)]
17/// enum HttpMethod {
18/// Get,
19/// Post,
20/// Put,
21/// Delete,
22/// Other,
23/// }
24///
25/// impl LabelEnum for HttpMethod {
26/// const CARDINALITY: usize = 5;
27/// const LABEL_NAME: &'static str = "method";
28///
29/// fn as_index(self) -> usize {
30/// self as usize
31/// }
32///
33/// fn from_index(index: usize) -> Self {
34/// match index {
35/// 0 => Self::Get,
36/// 1 => Self::Post,
37/// 2 => Self::Put,
38/// 3 => Self::Delete,
39/// _ => Self::Other,
40/// }
41/// }
42///
43/// fn variant_name(self) -> &'static str {
44/// match self {
45/// Self::Get => "get",
46/// Self::Post => "post",
47/// Self::Put => "put",
48/// Self::Delete => "delete",
49/// Self::Other => "other",
50/// }
51/// }
52/// }
53/// ```
54pub trait LabelEnum: Copy + Debug + 'static {
55 /// Number of variants in this enum.
56 const CARDINALITY: usize;
57
58 /// The Prometheus label name for this dimension.
59 ///
60 /// E.g., "method" for HttpMethod, "command" for RedisCommand.
61 const LABEL_NAME: &'static str;
62
63 /// Convert this variant to its array index.
64 fn as_index(self) -> usize;
65
66 /// Convert an array index back to a variant.
67 ///
68 /// Used for iteration during export. Should handle out-of-bounds
69 /// by returning a sensible default (e.g., an "Other" variant).
70 fn from_index(index: usize) -> Self;
71
72 /// Get the Prometheus label value for this variant.
73 ///
74 /// Should be lowercase, snake_case for Prometheus compatibility.
75 fn variant_name(self) -> &'static str;
76
77 /// Get the label name (convenience method for accessing LABEL_NAME).
78 #[inline]
79 fn label_name(&self) -> &'static str {
80 Self::LABEL_NAME
81 }
82}