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, ®istry).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}