Skip to content

Commit f6d702f

Browse files
authored
fix: don't assume Clone, register always (#6)
1 parent 714adcf commit f6d702f

5 files changed

Lines changed: 43 additions & 30 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ jobs:
2727
cache-on-failure: true
2828
- uses: taiki-e/install-action@nextest
2929
- run: cargo build --workspace
30+
- run: cargo test --doc --workspace
3031
- run: cargo nextest run --workspace
3132

3233
clippy:

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ name = "metrics-derive"
33
description = "Proc macro for automatically describing and initializing metrics"
44
version = "0.1.0"
55
edition = "2021"
6+
rust-version = "1.80"
67
license = "MIT OR Apache-2.0"
78
repository = "https://github.com/tempoxyz/metrics-derive"
89
exclude = [".github/"]

clippy.toml

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/expand.rs

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,6 @@ pub(crate) fn derive(node: &DeriveInput) -> Result<proc_macro2::TokenStream> {
2626
let metrics_attr = parse_metrics_attr(node)?;
2727
let metric_fields = parse_metric_fields(node)?;
2828

29-
let describe_doc = quote! {
30-
/// Describe all exposed metrics. Internally calls `describe_*` macros from
31-
/// the metrics crate according to the metric type.
32-
///
33-
/// See <https://docs.rs/metrics/latest/metrics/index.html#macros>
34-
};
3529
let register_and_describe = match &metrics_attr.scope {
3630
MetricsScope::Static(scope) => {
3731
let (field_inits, describes): (Vec<_>, Vec<_>) = metric_fields
@@ -93,31 +87,25 @@ pub(crate) fn derive(node: &DeriveInput) -> Result<proc_macro2::TokenStream> {
9387

9488
quote! {
9589
impl Default for #ty {
96-
fn default() -> Self {
97-
Self::new()
98-
}
99-
}
100-
101-
impl #ty {
10290
/// Creates a new instance of the metrics.
10391
///
10492
/// This initializes all metrics and registers them with the global recorder.
105-
/// Metrics are described and registered only once; subsequent calls return
106-
/// a clone of the initially registered metrics.
107-
///
108-
/// To re-register or register with labels, use [`Self::new_with_labels`].
109-
#vis fn new() -> Self {
110-
static __REGISTER_ONCE: ::std::sync::OnceLock<#ty> = ::std::sync::OnceLock::new();
111-
__REGISTER_ONCE.get_or_init(|| {
112-
Self::new_with_labels(::std::vec::Vec::<::metrics::Label>::new())
113-
})._clone()
93+
/// Metrics are described only once; see [`Self::describe`].
94+
fn default() -> Self {
95+
Self::_new_with_labels(::std::vec::Vec::<::metrics::Label>::new())
11496
}
97+
}
11598

99+
impl #ty {
116100
/// Creates a new instance of the metrics with the provided labels.
117101
///
118-
/// Unlike [`Self::new`], this does not cache the result, so it can be used
102+
/// Unlike [`Self::default`], this does not cache the result, so it can be used
119103
/// to re-register metrics or register with different labels.
120-
#vis fn new_with_labels(labels: impl ::metrics::IntoLabels + Clone) -> Self {
104+
#vis fn new_with_labels(labels: impl ::metrics::IntoLabels) -> Self {
105+
Self::_new_with_labels(labels.into_labels())
106+
}
107+
108+
fn _new_with_labels(labels: ::std::vec::Vec<::metrics::Label>) -> Self {
121109
Self::describe();
122110
::metrics::with_recorder(|__recorder| {
123111
static __METADATA: ::metrics::Metadata<'static> = ::metrics::Metadata::new(
@@ -133,13 +121,24 @@ pub(crate) fn derive(node: &DeriveInput) -> Result<proc_macro2::TokenStream> {
133121
})
134122
}
135123

136-
#describe_doc
124+
/// Describe all exposed metrics.
125+
///
126+
/// Internally, this calls the `describe_*` macros from the metrics crate
127+
/// according to the metric type.
128+
///
129+
/// This is done only once, to avoid multiple `describe` calls to the same
130+
/// recorder. If this is not preferred, you can call [`Self::force_describe`]
131+
/// directly.
132+
///
133+
/// See: <https://docs.rs/metrics/latest/metrics/index.html#macros>
137134
#vis fn describe() {
138135
static __DESCRIBE_ONCE: ::std::sync::Once = ::std::sync::Once::new();
139136
__DESCRIBE_ONCE.call_once(Self::force_describe);
140137
}
141138

142139
/// Unconditionally describes all metrics.
140+
///
141+
/// See [`Self::describe`].
143142
#vis fn force_describe() {
144143
::metrics::with_recorder(|__recorder| {
145144
#(#describes)*
@@ -209,12 +208,15 @@ pub(crate) fn derive(node: &DeriveInput) -> Result<proc_macro2::TokenStream> {
209208
///
210209
/// This initializes all metrics and registers them with the global recorder.
211210
#vis fn new(scope: &str) -> Self {
212-
Self::describe(scope);
213-
Self::new_with_labels(scope, ::std::vec::Vec::<::metrics::Label>::new())
211+
Self::_new_with_labels(scope, ::std::vec::Vec::<::metrics::Label>::new())
214212
}
215213

216214
/// Creates a new instance of the metrics with the provided scope and labels.
217-
#vis fn new_with_labels(scope: &str, labels: impl ::metrics::IntoLabels + Clone) -> Self {
215+
#vis fn new_with_labels(scope: &str, labels: impl ::metrics::IntoLabels) -> Self {
216+
Self::_new_with_labels(scope, labels.into_labels())
217+
}
218+
219+
fn _new_with_labels(scope: &str, labels: ::std::vec::Vec<::metrics::Label>) -> Self {
218220
Self::describe(scope);
219221
::metrics::with_recorder(|__recorder| {
220222
static __METADATA: ::metrics::Metadata<'static> = ::metrics::Metadata::new(
@@ -231,7 +233,10 @@ pub(crate) fn derive(node: &DeriveInput) -> Result<proc_macro2::TokenStream> {
231233
})
232234
}
233235

234-
#describe_doc
236+
/// Describe all exposed metrics. Internally calls `describe_*` macros from
237+
/// the metrics crate according to the metric type.
238+
///
239+
/// See: <https://docs.rs/metrics/latest/metrics/index.html#macros>
235240
#vis fn describe(scope: &str) {
236241
::metrics::with_recorder(|__recorder| {
237242
let __scope = scope;

tests/metrics.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use std::{
1313
#[allow(dead_code)]
1414
#[derive(Clone, Metrics)]
1515
#[metrics(scope = "metrics_custom")]
16-
struct CustomMetrics {
16+
pub struct CustomMetrics {
1717
#[metric(skip)]
1818
skipped_field_a: u8,
1919
/// A gauge with doc comment description.
@@ -36,6 +36,13 @@ struct CustomMetrics {
3636
skipped_field_e: u128,
3737
}
3838

39+
impl CustomMetrics {
40+
/// Custom new fn.
41+
pub fn new() -> Self {
42+
Self::new_with_labels(&[("type", "custom")])
43+
}
44+
}
45+
3946
#[allow(dead_code)]
4047
#[derive(Metrics)]
4148
#[metrics(dynamic = true)]

0 commit comments

Comments
 (0)