scuffle_metrics_derive/lib.rs
1//! A proc-macro to derive the `#[metrics]` attribute and the
2//! `#[derive(MetricEnum)]` attribute.
3//!
4//! For more information checkout the [`scuffle-metrics`](https://docs.rs/scuffle-metrics)
5//! crate.
6//!
7//! ## License
8//!
9//! This project is licensed under the MIT or Apache-2.0 license.
10//! You can choose between one of them if you use this work.
11//!
12//! `SPDX-License-Identifier: MIT OR Apache-2.0`
13#![deny(missing_docs)]
14#![deny(unsafe_code)]
15#![deny(unreachable_pub)]
16#![deny(clippy::mod_module_files)]
17
18use enum_impl::metric_enum_impl;
19use metrics_impl::metrics_impl;
20use proc_macro::TokenStream;
21
22mod enum_impl;
23mod metrics_impl;
24
25/// A macro used to create metric handlers.
26///
27/// You can change the crate by specifying `#[metrics(crate_path = "...")]`.
28///
29/// Module Attributes:
30///
31/// - `crate_path`: The `scuffle_metrics` crate path.
32/// - `rename`: The name of the metric container.
33///
34/// Function Attributes:
35///
36/// - `crate_path`: The `scuffle_metrics` crate path.
37/// - `builder`: The builder to use for the metric.
38/// - `unit`: The unit of the metric.
39/// - `rename`: The name of the metric.
40///
41/// Function Arguments Attributes:
42///
43/// - `rename`: The name of the argument.
44///
45/// When using the module, you do not need to attribute each function with the
46/// `#[metrics]` attribute. All non function definitions are ignored.
47///
48/// # Module Example
49///
50/// ```rust
51/// #[scuffle_metrics::metrics]
52/// mod example {
53/// use scuffle_metrics::{MetricEnum, collector::CounterU64};
54///
55/// #[derive(MetricEnum)]
56/// pub enum Kind {
57/// Http,
58/// Grpc,
59/// }
60///
61/// #[metrics(unit = "requests")]
62/// pub fn request(kind: Kind) -> CounterU64;
63/// }
64///
65/// // Increment the counter
66/// example::request(example::Kind::Http).incr();
67/// ```
68///
69/// # Function Example
70///
71/// ```rust
72/// # use scuffle_metrics::{MetricEnum, collector::CounterU64};
73/// # #[derive(MetricEnum)]
74/// # pub enum Kind {
75/// # Http,
76/// # Grpc,
77/// # }
78/// #[scuffle_metrics::metrics(unit = "requests")]
79/// pub fn request(kind: Kind) -> CounterU64;
80///
81/// // Increment the counter
82/// request(Kind::Http).incr();
83/// ```
84#[proc_macro_attribute]
85pub fn metrics(args: TokenStream, input: TokenStream) -> TokenStream {
86 match metrics_impl(args, input) {
87 Ok(tokens) => tokens.into(),
88 Err(err) => err.to_compile_error().into(),
89 }
90}
91
92/// Implements a conversion `Into<opentelemetry::Value>` for the enum.
93/// This allows the enum to be used as a metric label.
94///
95/// You can change the crate by specifying `#[metrics(crate_path = "...")]`.
96///
97/// Enum Attributes:
98///
99/// - `crate_path`: The `scuffle_metrics` crate path.
100///
101/// Enum Variant Attributes:
102///
103/// - `rename`: The name of the metric.
104#[proc_macro_derive(MetricEnum, attributes(metrics))]
105pub fn metric_enum(input: TokenStream) -> TokenStream {
106 match metric_enum_impl(input.into()) {
107 Ok(tokens) => tokens.into(),
108 Err(err) => err.to_compile_error().into(),
109 }
110}