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, histogram::Histogram},
103/// #     registry::{Register, Registry},
104/// # };
105/// #[derive(Default, fastmetrics_derive::Register)]
106/// struct Metrics {
107///     /// Total HTTP requests
108///     http_requests: Counter,
109///
110///     /// Duration of HTTP requests
111///     #[register(rename = "http_request_duration", unit(Seconds))]
112///     request_duration: Histogram,
113///
114///     #[register(flatten)]
115///     inner: InnerMetrics,
116///
117///     #[register(skip)]
118///     _skip: ()
119/// }
120///
121/// #[derive(Default, fastmetrics_derive::Register)]
122/// struct InnerMetrics {
123///     /// Inner counter help
124///     inner_counter: Counter,
125/// }
126///
127/// let mut registry = Registry::default();
128///
129/// let metrics = Metrics::default();
130/// metrics.register(&mut registry).unwrap();
131///
132/// let mut output = String::new();
133/// text::encode(&mut output, &registry).unwrap();
134/// // println!("{}", output);
135/// ```
136#[proc_macro_derive(Register, attributes(register))]
137pub fn derive_register_derive(input: TokenStream) -> TokenStream {
138    let input = parse_macro_input!(input as DeriveInput);
139    register::expand_derive(input).unwrap_or_else(Error::into_compile_error).into()
140}