fastmetrics_derive/
lib.rs

1//! This crate provides some derive macros for `fastmetrics`.
2
3#![deny(missing_docs)]
4#![deny(unsafe_code)]
5// False positive: https://github.com/rust-lang/rust/issues/129637
6// #![deny(unused_crate_dependencies)]
7
8mod encode_label_set;
9mod encode_label_value;
10mod register;
11mod state_set_value;
12mod utils;
13
14use proc_macro::TokenStream;
15use syn::{parse_macro_input, DeriveInput, Error};
16
17/// Derive the `EncodeLabelSet` trait for structs.
18///
19/// This macro automatically implements the `EncodeLabelSet` trait,
20/// which allows the struct to be used as a set of metric labels.
21/// This is useful for creating structured label sets that can be attached to metrics.
22///
23/// # Example
24///
25/// ```rust
26/// # use fastmetrics_derive::EncodeLabelSet;
27/// #[derive(EncodeLabelSet)]
28/// struct MyLabels {
29///     service: String,
30///     endpoint: String,
31/// }
32/// ```
33#[proc_macro_derive(EncodeLabelSet)]
34pub fn derive_encode_label_set(input: TokenStream) -> TokenStream {
35    let input = parse_macro_input!(input as DeriveInput);
36    encode_label_set::expand_derive(input)
37        .unwrap_or_else(Error::into_compile_error)
38        .into()
39}
40
41// Derive the `EncodeLabelValue` trait for enums.
42///
43/// This macro generates an implementation of the `EncodeLabelValue` trait,
44/// which allows them to be used as values in metric labels.
45/// This is useful for ensuring type safety when using enumerated values as labels.
46///
47/// # Example
48///
49/// ```rust
50/// # use fastmetrics_derive::EncodeLabelValue;
51/// #[derive(EncodeLabelValue)]
52/// enum Status {
53///     Success,
54///     Error,
55///     Pending,
56/// }
57/// ```
58#[proc_macro_derive(EncodeLabelValue)]
59pub fn derive_encode_label_value(input: TokenStream) -> TokenStream {
60    let input = parse_macro_input!(input as DeriveInput);
61    encode_label_value::expand_derive(input)
62        .unwrap_or_else(Error::into_compile_error)
63        .into()
64}
65
66/// Derive the `StateSetValue` trait for enums.
67///
68/// This macro implements the `StateSetValue` trait, which allows an enum
69/// to be used as a value in a state set metric.
70///
71/// # Example
72///
73/// ```rust
74/// # use fastmetrics_derive::StateSetValue;
75/// #[derive(PartialEq, StateSetValue)]
76/// enum ServiceState {
77///     Available,
78///     Degraded,
79///     Down,
80/// }
81/// ```
82#[proc_macro_derive(StateSetValue)]
83pub fn derive_state_set_value(input: TokenStream) -> TokenStream {
84    let input = parse_macro_input!(input as DeriveInput);
85    state_set_value::expand_derive(input)
86        .unwrap_or_else(Error::into_compile_error)
87        .into()
88}
89
90/// Derive the `Register` trait for structs.
91///
92/// This macro implements automatic registration of metrics with a registry.
93/// It processes `#[register]` attributes on struct fields to configure how
94/// each metric should be registered.
95///
96/// # Example
97///
98/// ```rust
99/// # use std::marker::PhantomData;
100/// # use fastmetrics::{
101/// #    format::text,
102/// #     metrics::{counter::Counter, gauge::Gauge, histogram::Histogram, family::Family},
103/// #     registry::{Register, Registry},
104/// # };
105/// static OVERRIDE_HELP: &str = "Custom help text that overrides doc comments";
106///
107/// #[derive(Default, fastmetrics_derive::Register)]
108/// struct DemoMetrics {
109///     /// My counter help
110///     #[register(rename = "my_counter")]
111///     counter_family: Family<(), Counter>,
112///
113///     /// My gauge help line 1
114///     /// help line 2
115///     /// help line 3
116///     #[register(rename = "my_gauge")]
117///     gauge: Gauge,
118///     
119///     // No help
120///     #[register(unit(Bytes))]
121///     counter: Counter,
122///
123///     /// This doc comment will be ignored
124///     #[register(help = OVERRIDE_HELP)]
125///     override_help_counter: Counter,
126///     
127///     /**
128///
129///     My histogram help line 1
130///
131///     help line 2
132///     help line 3
133///
134///     */
135///     #[register(rename = "my_histogram", unit = "bytes")]
136///     histogram: Histogram,
137///
138///     #[register(subsystem = "inner")]
139///     inner: InnerMetrics,
140///
141///     #[register(flatten)]
142///     flatten: FlattenMetrics,
143///
144///     // skip the field
145///     #[register(skip)]
146///     _skip: (),
147/// }
148///
149/// #[derive(Default, fastmetrics_derive::Register)]
150/// struct InnerMetrics {
151///     /// Inner counter help
152///     counter: Counter,
153/// }
154///
155/// #[derive(Default, fastmetrics_derive::Register)]
156/// struct FlattenMetrics {
157///     /// Flatten gauge help
158///     flatten_gauge: Gauge,
159/// }
160///
161/// let mut registry = Registry::builder().with_namespace("demo").build();
162///
163/// let metrics = DemoMetrics::default();
164/// metrics.register(&mut registry).unwrap();
165///
166/// let mut output = String::new();
167/// text::encode(&mut output, &registry).unwrap();
168/// // println!("{}", output);
169/// ```
170#[proc_macro_derive(Register, attributes(register))]
171pub fn derive_register_derive(input: TokenStream) -> TokenStream {
172    let input = parse_macro_input!(input as DeriveInput);
173    register::expand_derive(input).unwrap_or_else(Error::into_compile_error).into()
174}