From 0193688dac4ca646dbe44620040c20b9abf9bf5e Mon Sep 17 00:00:00 2001 From: Harry Barber <106155934+hlbarber@users.noreply.github.com> Date: Sat, 15 Jul 2023 13:59:14 +0100 Subject: [PATCH] Add metadata to metrics (#380) --- metrics-benchmark/src/main.rs | 8 +- metrics-exporter-prometheus/src/builder.rs | 49 +++--- metrics-exporter-prometheus/src/recorder.rs | 8 +- metrics-exporter-tcp/src/lib.rs | 8 +- metrics-macros/src/lib.rs | 169 ++++++++++++++++---- metrics-macros/src/tests.rs | 155 +++++++++++++++--- metrics-tracing-context/benches/layer.rs | 20 ++- metrics-tracing-context/src/lib.rs | 16 +- metrics-util/benches/filter.rs | 12 +- metrics-util/benches/prefix.rs | 8 +- metrics-util/benches/router.rs | 12 +- metrics-util/src/debugging.rs | 8 +- metrics-util/src/layers/fanout.rs | 38 +++-- metrics-util/src/layers/filter.rs | 49 ++++-- metrics-util/src/layers/mod.rs | 28 ++-- metrics-util/src/layers/prefix.rs | 41 +++-- metrics-util/src/layers/router.rs | 57 ++++--- metrics-util/src/recoverable.rs | 21 +-- metrics-util/src/test_util.rs | 42 ++--- metrics/benches/macros.rs | 10 +- metrics/examples/basic.rs | 8 +- metrics/src/lib.rs | 38 ++++- metrics/src/metadata.rs | 67 ++++++++ metrics/src/recorder.rs | 15 +- 24 files changed, 647 insertions(+), 240 deletions(-) create mode 100644 metrics/src/metadata.rs diff --git a/metrics-benchmark/src/main.rs b/metrics-benchmark/src/main.rs index 97d565f2..6321ebd9 100644 --- a/metrics-benchmark/src/main.rs +++ b/metrics-benchmark/src/main.rs @@ -3,7 +3,7 @@ use hdrhistogram::Histogram as HdrHistogram; use log::{error, info}; use metrics::{ gauge, histogram, increment_counter, register_counter, register_gauge, register_histogram, - Counter, Gauge, Histogram, Key, KeyName, Recorder, SharedString, Unit, + Counter, Gauge, Histogram, Key, KeyName, Metadata, Recorder, SharedString, Unit, }; use metrics_util::registry::{AtomicStorage, Registry}; use portable_atomic::AtomicU64; @@ -68,15 +68,15 @@ impl Recorder for BenchmarkingRecorder { fn describe_histogram(&self, _: KeyName, _: Option, _: SharedString) {} - fn register_counter(&self, key: &Key) -> Counter { + fn register_counter(&self, key: &Key, _metadata: &Metadata<'_>) -> Counter { self.registry.get_or_create_counter(key, |c| Counter::from_arc(c.clone())) } - fn register_gauge(&self, key: &Key) -> Gauge { + fn register_gauge(&self, key: &Key, _metadata: &Metadata<'_>) -> Gauge { self.registry.get_or_create_gauge(key, |g| Gauge::from_arc(g.clone())) } - fn register_histogram(&self, key: &Key) -> Histogram { + fn register_histogram(&self, key: &Key, _metadata: &Metadata<'_>) -> Histogram { self.registry.get_or_create_histogram(key, |h| Histogram::from_arc(h.clone())) } } diff --git a/metrics-exporter-prometheus/src/builder.rs b/metrics-exporter-prometheus/src/builder.rs index 53824140..26ba6353 100644 --- a/metrics-exporter-prometheus/src/builder.rs +++ b/metrics-exporter-prometheus/src/builder.rs @@ -577,13 +577,16 @@ mod tests { use super::{Matcher, PrometheusBuilder}; + static METADATA: metrics::Metadata = + metrics::Metadata::new(module_path!(), metrics::Level::INFO, Some(module_path!())); + #[test] fn test_render() { let recorder = PrometheusBuilder::new().set_quantiles(&[0.0, 1.0]).unwrap().build_recorder(); let key = Key::from_name("basic_counter"); - let counter1 = recorder.register_counter(&key); + let counter1 = recorder.register_counter(&key, &METADATA); counter1.increment(42); let handle = recorder.handle(); @@ -594,7 +597,7 @@ mod tests { let labels = vec![Label::new("wutang", "forever")]; let key = Key::from_parts("basic_gauge", labels); - let gauge1 = recorder.register_gauge(&key); + let gauge1 = recorder.register_gauge(&key, &METADATA); gauge1.set(-3.14); let rendered = handle.render(); let expected_gauge = format!( @@ -605,7 +608,7 @@ mod tests { assert_eq!(rendered, expected_gauge); let key = Key::from_name("basic_histogram"); - let histogram1 = recorder.register_histogram(&key); + let histogram1 = recorder.register_histogram(&key, &METADATA); histogram1.record(12.0); let rendered = handle.render(); @@ -647,19 +650,19 @@ mod tests { .build_recorder(); let full_key = Key::from_name("metrics.testing_foo"); - let full_key_histo = recorder.register_histogram(&full_key); + let full_key_histo = recorder.register_histogram(&full_key, &METADATA); full_key_histo.record(FULL_VALUES[0]); let prefix_key = Key::from_name("metrics.testing_bar"); - let prefix_key_histo = recorder.register_histogram(&prefix_key); + let prefix_key_histo = recorder.register_histogram(&prefix_key, &METADATA); prefix_key_histo.record(PREFIX_VALUES[1]); let suffix_key = Key::from_name("metrics_testin_foo"); - let suffix_key_histo = recorder.register_histogram(&suffix_key); + let suffix_key_histo = recorder.register_histogram(&suffix_key, &METADATA); suffix_key_histo.record(SUFFIX_VALUES[2]); let default_key = Key::from_name("metrics.wee"); - let default_key_histo = recorder.register_histogram(&default_key); + let default_key_histo = recorder.register_histogram(&default_key, &METADATA); default_key_histo.record(DEFAULT_VALUES[2] + 1.0); let full_data = concat!( @@ -722,15 +725,15 @@ mod tests { .build_with_clock(clock); let key = Key::from_name("basic_counter"); - let counter1 = recorder.register_counter(&key); + let counter1 = recorder.register_counter(&key, &METADATA); counter1.increment(42); let key = Key::from_name("basic_gauge"); - let gauge1 = recorder.register_gauge(&key); + let gauge1 = recorder.register_gauge(&key, &METADATA); gauge1.set(-3.14); let key = Key::from_name("basic_histogram"); - let histo1 = recorder.register_histogram(&key); + let histo1 = recorder.register_histogram(&key, &METADATA); histo1.record(1.0); let handle = recorder.handle(); @@ -772,15 +775,15 @@ mod tests { .build_with_clock(clock); let key = Key::from_name("basic_counter"); - let counter1 = recorder.register_counter(&key); + let counter1 = recorder.register_counter(&key, &METADATA); counter1.increment(42); let key = Key::from_name("basic_gauge"); - let gauge1 = recorder.register_gauge(&key); + let gauge1 = recorder.register_gauge(&key, &METADATA); gauge1.set(-3.14); let key = Key::from_name("basic_histogram"); - let histo1 = recorder.register_histogram(&key); + let histo1 = recorder.register_histogram(&key, &METADATA); histo1.record(1.0); let handle = recorder.handle(); @@ -821,15 +824,15 @@ mod tests { .build_with_clock(clock); let key = Key::from_name("basic_counter"); - let counter1 = recorder.register_counter(&key); + let counter1 = recorder.register_counter(&key, &METADATA); counter1.increment(42); let key = Key::from_name("basic_gauge"); - let gauge1 = recorder.register_gauge(&key); + let gauge1 = recorder.register_gauge(&key, &METADATA); gauge1.set(-3.14); let key = Key::from_name("basic_histogram"); - let histo1 = recorder.register_histogram(&key); + let histo1 = recorder.register_histogram(&key, &METADATA); histo1.record(1.0); let handle = recorder.handle(); @@ -853,7 +856,7 @@ mod tests { assert_eq!(rendered, expected); let key = Key::from_parts("basic_histogram", vec![Label::new("type", "special")]); - let histo2 = recorder.register_histogram(&key); + let histo2 = recorder.register_histogram(&key, &METADATA); histo2.record(2.0); let expected_second = concat!( @@ -896,11 +899,11 @@ mod tests { .build_with_clock(clock); let key = Key::from_name("basic_counter"); - let counter1 = recorder.register_counter(&key); + let counter1 = recorder.register_counter(&key, &METADATA); counter1.increment(42); let key = Key::from_name("basic_gauge"); - let gauge1 = recorder.register_gauge(&key); + let gauge1 = recorder.register_gauge(&key, &METADATA); gauge1.set(-3.14); let handle = recorder.handle(); @@ -945,7 +948,7 @@ mod tests { .build_with_clock(clock); let key = Key::from_name("basic_counter"); - let counter1 = recorder.register_counter(&key); + let counter1 = recorder.register_counter(&key, &METADATA); counter1.increment(42); // First render, which starts tracking the counter in the recency state. @@ -984,7 +987,7 @@ mod tests { .add_global_label("foo", "bar") .build_recorder(); let key = Key::from_name("basic_counter"); - let counter1 = recorder.register_counter(&key); + let counter1 = recorder.register_counter(&key, &METADATA); counter1.increment(42); let handle = recorder.handle(); @@ -1000,7 +1003,7 @@ mod tests { let key = Key::from_name("overridden").with_extra_labels(vec![Label::new("foo", "overridden")]); - let counter1 = recorder.register_counter(&key); + let counter1 = recorder.register_counter(&key, &METADATA); counter1.increment(1); let handle = recorder.handle(); @@ -1018,7 +1021,7 @@ mod tests { let key = Key::from_name(key_name.clone()) .with_extra_labels(vec![Label::new("øhno", "\"yeet\nies\\\"")]); recorder.describe_counter(key_name, None, "\"Simplë stuff.\nRëally.\"".into()); - let counter1 = recorder.register_counter(&key); + let counter1 = recorder.register_counter(&key, &METADATA); counter1.increment(1); let handle = recorder.handle(); diff --git a/metrics-exporter-prometheus/src/recorder.rs b/metrics-exporter-prometheus/src/recorder.rs index 42582c61..699f0d75 100644 --- a/metrics-exporter-prometheus/src/recorder.rs +++ b/metrics-exporter-prometheus/src/recorder.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use std::sync::{PoisonError, RwLock}; use indexmap::IndexMap; -use metrics::{Counter, Gauge, Histogram, Key, KeyName, Recorder, SharedString, Unit}; +use metrics::{Counter, Gauge, Histogram, Key, KeyName, Metadata, Recorder, SharedString, Unit}; use metrics_util::registry::{Recency, Registry}; use quanta::Instant; @@ -246,15 +246,15 @@ impl Recorder for PrometheusRecorder { self.add_description_if_missing(&key_name, description); } - fn register_counter(&self, key: &Key) -> Counter { + fn register_counter(&self, key: &Key, _metadata: &Metadata<'_>) -> Counter { self.inner.registry.get_or_create_counter(key, |c| c.clone().into()) } - fn register_gauge(&self, key: &Key) -> Gauge { + fn register_gauge(&self, key: &Key, _metadata: &Metadata<'_>) -> Gauge { self.inner.registry.get_or_create_gauge(key, |c| c.clone().into()) } - fn register_histogram(&self, key: &Key) -> Histogram { + fn register_histogram(&self, key: &Key, _metadata: &Metadata<'_>) -> Histogram { self.inner.registry.get_or_create_histogram(key, |c| c.clone().into()) } } diff --git a/metrics-exporter-tcp/src/lib.rs b/metrics-exporter-tcp/src/lib.rs index 6f74e539..0c4fc7c8 100644 --- a/metrics-exporter-tcp/src/lib.rs +++ b/metrics-exporter-tcp/src/lib.rs @@ -62,7 +62,7 @@ use std::{ use bytes::Bytes; use crossbeam_channel::{bounded, unbounded, Receiver, Sender}; use metrics::{ - Counter, CounterFn, Gauge, GaugeFn, Histogram, HistogramFn, Key, KeyName, Recorder, + Counter, CounterFn, Gauge, GaugeFn, Histogram, HistogramFn, Key, KeyName, Metadata, Recorder, SetRecorderError, SharedString, Unit, }; use mio::{ @@ -333,15 +333,15 @@ impl Recorder for TcpRecorder { self.state.register_metric(key_name, MetricType::Histogram, unit, description); } - fn register_counter(&self, key: &Key) -> Counter { + fn register_counter(&self, key: &Key, _metadata: &Metadata<'_>) -> Counter { Counter::from_arc(Arc::new(Handle::new(key.clone(), self.state.clone()))) } - fn register_gauge(&self, key: &Key) -> Gauge { + fn register_gauge(&self, key: &Key, _metadata: &Metadata<'_>) -> Gauge { Gauge::from_arc(Arc::new(Handle::new(key.clone(), self.state.clone()))) } - fn register_histogram(&self, key: &Key) -> Histogram { + fn register_histogram(&self, key: &Key, _metadata: &Metadata<'_>) -> Histogram { Histogram::from_arc(Arc::new(Handle::new(key.clone(), self.state.clone()))) } } diff --git a/metrics-macros/src/lib.rs b/metrics-macros/src/lib.rs index 6b11132f..7d84926e 100644 --- a/metrics-macros/src/lib.rs +++ b/metrics-macros/src/lib.rs @@ -5,8 +5,9 @@ use self::proc_macro::TokenStream; use proc_macro2::TokenStream as TokenStream2; use quote::{format_ident, quote, ToTokens}; use syn::parse::{Error, Parse, ParseStream, Result}; +use syn::token::{Colon, Comma}; use syn::{parse::discouraged::Speculative, Lit}; -use syn::{parse_macro_input, Expr, Token}; +use syn::{parse_macro_input, Expr, LitStr, Token}; #[cfg(test)] mod tests; @@ -17,11 +18,15 @@ enum Labels { } struct WithoutExpression { + target: Option, + level: Option, key: Expr, labels: Option, } struct WithExpression { + target: Option, + level: Option, key: Expr, op_value: Expr, labels: Option, @@ -35,15 +40,19 @@ struct Description { impl Parse for WithoutExpression { fn parse(mut input: ParseStream) -> Result { + let target = parse_target(&mut input)?; + let level = parse_level(&mut input)?; let key = input.parse::()?; let labels = parse_labels(&mut input)?; - Ok(WithoutExpression { key, labels }) + Ok(WithoutExpression { target, level, key, labels }) } } impl Parse for WithExpression { fn parse(mut input: ParseStream) -> Result { + let target = parse_target(&mut input)?; + let level = parse_level(&mut input)?; let key = input.parse::()?; input.parse::()?; @@ -51,7 +60,7 @@ impl Parse for WithExpression { let labels = parse_labels(&mut input)?; - Ok(WithExpression { key, op_value, labels }) + Ok(WithExpression { target, level, key, op_value, labels }) } } @@ -131,74 +140,90 @@ pub fn describe_histogram(input: TokenStream) -> TokenStream { #[proc_macro] pub fn register_counter(input: TokenStream) -> TokenStream { - let WithoutExpression { key, labels } = parse_macro_input!(input as WithoutExpression); + let WithoutExpression { target, level, key, labels } = + parse_macro_input!(input as WithoutExpression); - get_register_and_op_code::("counter", key, labels, None).into() + get_register_and_op_code::(target, level, "counter", key, labels, None).into() } #[proc_macro] pub fn register_gauge(input: TokenStream) -> TokenStream { - let WithoutExpression { key, labels } = parse_macro_input!(input as WithoutExpression); + let WithoutExpression { target, level, key, labels } = + parse_macro_input!(input as WithoutExpression); - get_register_and_op_code::("gauge", key, labels, None).into() + get_register_and_op_code::(target, level, "gauge", key, labels, None).into() } #[proc_macro] pub fn register_histogram(input: TokenStream) -> TokenStream { - let WithoutExpression { key, labels } = parse_macro_input!(input as WithoutExpression); + let WithoutExpression { target, level, key, labels } = + parse_macro_input!(input as WithoutExpression); - get_register_and_op_code::("histogram", key, labels, None).into() + get_register_and_op_code::(target, level, "histogram", key, labels, None).into() } #[proc_macro] pub fn increment_counter(input: TokenStream) -> TokenStream { - let WithoutExpression { key, labels } = parse_macro_input!(input as WithoutExpression); + let WithoutExpression { target, level, key, labels } = + parse_macro_input!(input as WithoutExpression); let op_value = quote! { 1 }; - get_register_and_op_code("counter", key, labels, Some(("increment", op_value))).into() + get_register_and_op_code(target, level, "counter", key, labels, Some(("increment", op_value))) + .into() } #[proc_macro] pub fn counter(input: TokenStream) -> TokenStream { - let WithExpression { key, op_value, labels } = parse_macro_input!(input as WithExpression); + let WithExpression { target, level, key, op_value, labels } = + parse_macro_input!(input as WithExpression); - get_register_and_op_code("counter", key, labels, Some(("increment", op_value))).into() + get_register_and_op_code(target, level, "counter", key, labels, Some(("increment", op_value))) + .into() } #[proc_macro] pub fn absolute_counter(input: TokenStream) -> TokenStream { - let WithExpression { key, op_value, labels } = parse_macro_input!(input as WithExpression); + let WithExpression { target, level, key, op_value, labels } = + parse_macro_input!(input as WithExpression); - get_register_and_op_code("counter", key, labels, Some(("absolute", op_value))).into() + get_register_and_op_code(target, level, "counter", key, labels, Some(("absolute", op_value))) + .into() } #[proc_macro] pub fn increment_gauge(input: TokenStream) -> TokenStream { - let WithExpression { key, op_value, labels } = parse_macro_input!(input as WithExpression); + let WithExpression { target, level, key, op_value, labels } = + parse_macro_input!(input as WithExpression); - get_register_and_op_code("gauge", key, labels, Some(("increment", op_value))).into() + get_register_and_op_code(target, level, "gauge", key, labels, Some(("increment", op_value))) + .into() } #[proc_macro] pub fn decrement_gauge(input: TokenStream) -> TokenStream { - let WithExpression { key, op_value, labels } = parse_macro_input!(input as WithExpression); + let WithExpression { target, level, key, op_value, labels } = + parse_macro_input!(input as WithExpression); - get_register_and_op_code("gauge", key, labels, Some(("decrement", op_value))).into() + get_register_and_op_code(target, level, "gauge", key, labels, Some(("decrement", op_value))) + .into() } #[proc_macro] pub fn gauge(input: TokenStream) -> TokenStream { - let WithExpression { key, op_value, labels } = parse_macro_input!(input as WithExpression); + let WithExpression { target, level, key, op_value, labels } = + parse_macro_input!(input as WithExpression); - get_register_and_op_code("gauge", key, labels, Some(("set", op_value))).into() + get_register_and_op_code(target, level, "gauge", key, labels, Some(("set", op_value))).into() } #[proc_macro] pub fn histogram(input: TokenStream) -> TokenStream { - let WithExpression { key, op_value, labels } = parse_macro_input!(input as WithExpression); + let WithExpression { target, level, key, op_value, labels } = + parse_macro_input!(input as WithExpression); - get_register_and_op_code("histogram", key, labels, Some(("record", op_value))).into() + get_register_and_op_code(target, level, "histogram", key, labels, Some(("record", op_value))) + .into() } fn get_describe_code( @@ -225,6 +250,8 @@ fn get_describe_code( } fn get_register_and_op_code( + target: Option, + level: Option, metric_type: &str, name: Expr, labels: Option, @@ -234,7 +261,7 @@ where V: ToTokens, { let register_ident = format_ident!("register_{}", metric_type); - let statics = generate_statics(&name, &labels); + let statics = generate_statics(&target, &level, &name, &labels); let (locals, metric_key) = generate_metric_key(&name, &labels); match op { Some((op_type, op_value)) => { @@ -253,7 +280,7 @@ where // Only do this work if there's a recorder installed. if let Some(recorder) = ::metrics::try_recorder() { #locals - let handle = recorder.#register_ident(#metric_key); + let handle = recorder.#register_ident(#metric_key, &METADATA); handle.#op_ident(#op_value); } } @@ -265,7 +292,7 @@ where { #statics #locals - ::metrics::recorder().#register_ident(#metric_key) + ::metrics::recorder().#register_ident(#metric_key, &METADATA) } } } @@ -289,7 +316,12 @@ fn labels_are_fast_path(labels: &Labels) -> bool { } } -fn generate_statics(name: &Expr, labels: &Option) -> TokenStream2 { +fn generate_statics( + target: &Option, + level: &Option, + name: &Expr, + labels: &Option, +) -> TokenStream2 { // Create the static for the name, if possible. let use_name_static = name_is_fast_path(name); let name_static = if use_name_static { @@ -347,10 +379,32 @@ fn generate_statics(name: &Expr, labels: &Option) -> TokenStream2 { quote! {} }; + let target = if let Some(target) = target { + quote! { #target } + } else { + quote! { + module_path!() + } + }; + let level = if let Some(level) = level { + quote! { #level } + } else { + quote! { ::metrics::Level::INFO } + }; + + let metadata_static = quote! { + static METADATA: ::metrics::Metadata<'static> = ::metrics::Metadata::new( + #target, + #level, + Some(module_path!()), + ); + }; + quote! { #name_static #labels_static #key_static + #metadata_static } } @@ -414,6 +468,67 @@ fn labels_to_quoted(labels: &Labels) -> proc_macro2::TokenStream { } } +mod kw { + syn::custom_keyword!(target); + syn::custom_keyword!(level); +} + +struct Target { + _target_key: kw::target, + _colon: Colon, + target_value: LitStr, +} + +impl Parse for Target { + fn parse(input: ParseStream) -> Result { + Ok(Target { + _target_key: input.parse()?, + _colon: input.parse()?, + target_value: input.parse()?, + }) + } +} + +fn parse_target(input: &mut ParseStream) -> Result> { + let lookahead = input.lookahead1(); + let opt_target = if lookahead.peek(kw::target) { + let target = input.parse::()?.target_value; + let _colon: Comma = input.parse()?; + Some(target) + } else { + None + }; + Ok(opt_target) +} + +struct Level { + _level_key: kw::level, + _colon: Colon, + target_value: Expr, +} + +impl Parse for Level { + fn parse(input: ParseStream) -> Result { + Ok(Self { + _level_key: input.parse()?, + _colon: input.parse()?, + target_value: input.parse()?, + }) + } +} + +fn parse_level(input: &mut ParseStream) -> Result> { + let lookahead = input.lookahead1(); + let opt_level = if lookahead.peek(kw::level) { + let level = input.parse::()?.target_value; + let _colon: Comma = input.parse()?; + Some(level) + } else { + None + }; + Ok(opt_level) +} + fn parse_labels(input: &mut ParseStream) -> Result> { if input.is_empty() { return Ok(None); diff --git a/metrics-macros/src/tests.rs b/metrics-macros/src/tests.rs index 46a5d29f..f682ad68 100644 --- a/metrics-macros/src/tests.rs +++ b/metrics-macros/src/tests.rs @@ -175,13 +175,67 @@ fn test_get_describe_code_with_constants_and_with_relative_unit() { #[test] fn test_get_register_and_op_code_register_static_name_no_labels() { - let stream = get_register_and_op_code::("mytype", parse_quote! {"mykeyname"}, None, None); + let stream = get_register_and_op_code::( + None, + None, + "mytype", + parse_quote! {"mykeyname"}, + None, + None, + ); let expected = concat!( "{ ", "static METRIC_NAME : & 'static str = \"mykeyname\" ; ", "static METRIC_KEY : :: metrics :: Key = :: metrics :: Key :: from_static_name (METRIC_NAME) ; ", - ":: metrics :: recorder () . register_mytype (& METRIC_KEY) ", + "static METADATA : :: metrics :: Metadata < 'static > = :: metrics :: Metadata :: new (module_path ! () , :: metrics :: Level :: INFO , Some (module_path ! ()) ,) ; ", + ":: metrics :: recorder () . register_mytype (& METRIC_KEY , & METADATA) ", + "}", + ); + + assert_eq!(stream.to_string(), expected); +} + +#[test] +fn test_get_register_and_op_code_register_static_name_no_labels_target() { + let stream = get_register_and_op_code::( + Some(parse_quote! { "foo" }), + None, + "mytype", + parse_quote! {"mykeyname"}, + None, + None, + ); + + let expected = concat!( + "{ ", + "static METRIC_NAME : & 'static str = \"mykeyname\" ; ", + "static METRIC_KEY : :: metrics :: Key = :: metrics :: Key :: from_static_name (METRIC_NAME) ; ", + "static METADATA : :: metrics :: Metadata < 'static > = :: metrics :: Metadata :: new (\"foo\" , :: metrics :: Level :: INFO , Some (module_path ! ()) ,) ; ", + ":: metrics :: recorder () . register_mytype (& METRIC_KEY , & METADATA) ", + "}", + ); + + assert_eq!(stream.to_string(), expected); +} + +#[test] +fn test_get_register_and_op_code_register_static_name_no_labels_level() { + let stream = get_register_and_op_code::( + None, + Some(parse_quote! { metrics::Level::TRACE }), + "mytype", + parse_quote! {"mykeyname"}, + None, + None, + ); + + let expected = concat!( + "{ ", + "static METRIC_NAME : & 'static str = \"mykeyname\" ; ", + "static METRIC_KEY : :: metrics :: Key = :: metrics :: Key :: from_static_name (METRIC_NAME) ; ", + "static METADATA : :: metrics :: Metadata < 'static > = :: metrics :: Metadata :: new (module_path ! () , metrics :: Level :: TRACE , Some (module_path ! ()) ,) ; ", + ":: metrics :: recorder () . register_mytype (& METRIC_KEY , & METADATA) ", "}", ); @@ -191,15 +245,23 @@ fn test_get_register_and_op_code_register_static_name_no_labels() { #[test] fn test_get_register_and_op_code_register_static_name_static_inline_labels() { let labels = Labels::Inline(vec![(parse_quote! { "key1" }, parse_quote! { "value1" })]); - let stream = - get_register_and_op_code::("mytype", parse_quote! {"mykeyname"}, Some(labels), None); + let stream = get_register_and_op_code::( + None, + None, + "mytype", + parse_quote! {"mykeyname"}, + Some(labels), + None, + ); let expected = concat!( "{ ", "static METRIC_NAME : & 'static str = \"mykeyname\" ; ", + "static METRIC_LABELS : [:: metrics :: Label ; 1usize] = [:: metrics :: Label :: from_static_parts (\"key1\" , \"value1\")] ; ", "static METRIC_KEY : :: metrics :: Key = :: metrics :: Key :: from_static_parts (METRIC_NAME , & METRIC_LABELS) ; ", - ":: metrics :: recorder () . register_mytype (& METRIC_KEY) ", + "static METADATA : :: metrics :: Metadata < 'static > = :: metrics :: Metadata :: new (module_path ! () , :: metrics :: Level :: INFO , Some (module_path ! ()) ,) ; ", + ":: metrics :: recorder () . register_mytype (& METRIC_KEY , & METADATA) ", "}", ); @@ -209,14 +271,21 @@ fn test_get_register_and_op_code_register_static_name_static_inline_labels() { #[test] fn test_get_register_and_op_code_register_static_name_dynamic_inline_labels() { let labels = Labels::Inline(vec![(parse_quote! { "key1" }, parse_quote! { &value1 })]); - let stream = - get_register_and_op_code::("mytype", parse_quote! {"mykeyname"}, Some(labels), None); + let stream = get_register_and_op_code::( + None, + None, + "mytype", + parse_quote! {"mykeyname"}, + Some(labels), + None, + ); let expected = concat!( "{ ", "static METRIC_NAME : & 'static str = \"mykeyname\" ; ", + "static METADATA : :: metrics :: Metadata < 'static > = :: metrics :: Metadata :: new (module_path ! () , :: metrics :: Level :: INFO , Some (module_path ! ()) ,) ; ", "let key = :: metrics :: Key :: from_parts (METRIC_NAME , vec ! [:: metrics :: Label :: new (\"key1\" , & value1)]) ; ", - ":: metrics :: recorder () . register_mytype (& key) ", + ":: metrics :: recorder () . register_mytype (& key , & METADATA) ", "}", ); @@ -227,6 +296,8 @@ fn test_get_register_and_op_code_register_static_name_dynamic_inline_labels() { #[test] fn test_get_register_and_op_code_register_static_name_existing_labels() { let stream = get_register_and_op_code::( + None, + None, "mytype", parse_quote! {"mykeyname"}, Some(Labels::Existing(parse_quote! { mylabels })), @@ -236,8 +307,9 @@ fn test_get_register_and_op_code_register_static_name_existing_labels() { let expected = concat!( "{ ", "static METRIC_NAME : & 'static str = \"mykeyname\" ; ", + "static METADATA : :: metrics :: Metadata < 'static > = :: metrics :: Metadata :: new (module_path ! () , :: metrics :: Level :: INFO , Some (module_path ! ()) ,) ; ", "let key = :: metrics :: Key :: from_parts (METRIC_NAME , mylabels) ; ", - ":: metrics :: recorder () . register_mytype (& key) ", + ":: metrics :: recorder () . register_mytype (& key , & METADATA) ", "}", ); @@ -247,6 +319,8 @@ fn test_get_register_and_op_code_register_static_name_existing_labels() { #[test] fn test_get_register_and_op_code_register_owned_name_no_labels() { let stream = get_register_and_op_code::( + None, + None, "mytype", parse_quote! { String::from("owned") }, None, @@ -255,8 +329,9 @@ fn test_get_register_and_op_code_register_owned_name_no_labels() { let expected = concat!( "{ ", + "static METADATA : :: metrics :: Metadata < 'static > = :: metrics :: Metadata :: new (module_path ! () , :: metrics :: Level :: INFO , Some (module_path ! ()) ,) ; ", "let key = :: metrics :: Key :: from_name (String :: from (\"owned\")) ; ", - ":: metrics :: recorder () . register_mytype (& key) ", + ":: metrics :: recorder () . register_mytype (& key , & METADATA) ", "}", ); @@ -267,6 +342,8 @@ fn test_get_register_and_op_code_register_owned_name_no_labels() { fn test_get_register_and_op_code_register_owned_name_static_inline_labels() { let labels = Labels::Inline(vec![(parse_quote! { "key1" }, parse_quote! { "value1" })]); let stream = get_register_and_op_code::( + None, + None, "mytype", parse_quote! { String::from("owned") }, Some(labels), @@ -276,8 +353,9 @@ fn test_get_register_and_op_code_register_owned_name_static_inline_labels() { let expected = concat!( "{ ", "static METRIC_LABELS : [:: metrics :: Label ; 1usize] = [:: metrics :: Label :: from_static_parts (\"key1\" , \"value1\")] ; ", + "static METADATA : :: metrics :: Metadata < 'static > = :: metrics :: Metadata :: new (module_path ! () , :: metrics :: Level :: INFO , Some (module_path ! ()) ,) ; ", "let key = :: metrics :: Key :: from_static_labels (String :: from (\"owned\") , & METRIC_LABELS) ; ", - ":: metrics :: recorder () . register_mytype (& key) ", + ":: metrics :: recorder () . register_mytype (& key , & METADATA) ", "}", ); @@ -288,6 +366,8 @@ fn test_get_register_and_op_code_register_owned_name_static_inline_labels() { fn test_get_register_and_op_code_register_owned_name_dynamic_inline_labels() { let labels = Labels::Inline(vec![(parse_quote! { "key1" }, parse_quote! { &value1 })]); let stream = get_register_and_op_code::( + None, + None, "mytype", parse_quote! { String::from("owned") }, Some(labels), @@ -296,8 +376,9 @@ fn test_get_register_and_op_code_register_owned_name_dynamic_inline_labels() { let expected = concat!( "{ ", + "static METADATA : :: metrics :: Metadata < 'static > = :: metrics :: Metadata :: new (module_path ! () , :: metrics :: Level :: INFO , Some (module_path ! ()) ,) ; ", "let key = :: metrics :: Key :: from_parts (String :: from (\"owned\") , vec ! [:: metrics :: Label :: new (\"key1\" , & value1)]) ; ", - ":: metrics :: recorder () . register_mytype (& key) ", + ":: metrics :: recorder () . register_mytype (& key , & METADATA) ", "}", ); @@ -308,6 +389,8 @@ fn test_get_register_and_op_code_register_owned_name_dynamic_inline_labels() { #[test] fn test_get_register_and_op_code_register_owned_name_existing_labels() { let stream = get_register_and_op_code::( + None, + None, "mytype", parse_quote! { String::from("owned") }, Some(Labels::Existing(parse_quote! { mylabels })), @@ -316,8 +399,9 @@ fn test_get_register_and_op_code_register_owned_name_existing_labels() { let expected = concat!( "{ ", + "static METADATA : :: metrics :: Metadata < 'static > = :: metrics :: Metadata :: new (module_path ! () , :: metrics :: Level :: INFO , Some (module_path ! ()) ,) ; ", "let key = :: metrics :: Key :: from_parts (String :: from (\"owned\") , mylabels) ; ", - ":: metrics :: recorder () . register_mytype (& key) ", + ":: metrics :: recorder () . register_mytype (& key , & METADATA) ", "}", ); @@ -327,6 +411,8 @@ fn test_get_register_and_op_code_register_owned_name_existing_labels() { #[test] fn test_get_register_and_op_code_op_static_name_no_labels() { let stream = get_register_and_op_code( + None, + None, "mytype", parse_quote! {"mykeyname"}, None, @@ -337,8 +423,9 @@ fn test_get_register_and_op_code_op_static_name_no_labels() { "{ ", "static METRIC_NAME : & 'static str = \"mykeyname\" ; ", "static METRIC_KEY : :: metrics :: Key = :: metrics :: Key :: from_static_name (METRIC_NAME) ; ", + "static METADATA : :: metrics :: Metadata < 'static > = :: metrics :: Metadata :: new (module_path ! () , :: metrics :: Level :: INFO , Some (module_path ! ()) ,) ; ", "if let Some (recorder) = :: metrics :: try_recorder () { ", - "let handle = recorder . register_mytype (& METRIC_KEY) ; ", + "let handle = recorder . register_mytype (& METRIC_KEY , & METADATA) ; ", "handle . myop (1) ; ", "} ", "}", @@ -351,6 +438,8 @@ fn test_get_register_and_op_code_op_static_name_no_labels() { fn test_get_register_and_op_code_op_static_name_static_inline_labels() { let labels = Labels::Inline(vec![(parse_quote! { "key1" }, parse_quote! { "value1" })]); let stream = get_register_and_op_code( + None, + None, "mytype", parse_quote! {"mykeyname"}, Some(labels), @@ -362,8 +451,9 @@ fn test_get_register_and_op_code_op_static_name_static_inline_labels() { "static METRIC_NAME : & 'static str = \"mykeyname\" ; ", "static METRIC_LABELS : [:: metrics :: Label ; 1usize] = [:: metrics :: Label :: from_static_parts (\"key1\" , \"value1\")] ; ", "static METRIC_KEY : :: metrics :: Key = :: metrics :: Key :: from_static_parts (METRIC_NAME , & METRIC_LABELS) ; ", + "static METADATA : :: metrics :: Metadata < 'static > = :: metrics :: Metadata :: new (module_path ! () , :: metrics :: Level :: INFO , Some (module_path ! ()) ,) ; ", "if let Some (recorder) = :: metrics :: try_recorder () { ", - "let handle = recorder . register_mytype (& METRIC_KEY) ; ", + "let handle = recorder . register_mytype (& METRIC_KEY , & METADATA) ; ", "handle . myop (1) ; ", "} ", "}", @@ -376,6 +466,8 @@ fn test_get_register_and_op_code_op_static_name_static_inline_labels() { fn test_get_register_and_op_code_op_static_name_dynamic_inline_labels() { let labels = Labels::Inline(vec![(parse_quote! { "key1" }, parse_quote! { &value1 })]); let stream = get_register_and_op_code( + None, + None, "mytype", parse_quote! {"mykeyname"}, Some(labels), @@ -385,9 +477,10 @@ fn test_get_register_and_op_code_op_static_name_dynamic_inline_labels() { let expected = concat!( "{ ", "static METRIC_NAME : & 'static str = \"mykeyname\" ; ", + "static METADATA : :: metrics :: Metadata < 'static > = :: metrics :: Metadata :: new (module_path ! () , :: metrics :: Level :: INFO , Some (module_path ! ()) ,) ; ", "if let Some (recorder) = :: metrics :: try_recorder () { ", "let key = :: metrics :: Key :: from_parts (METRIC_NAME , vec ! [:: metrics :: Label :: new (\"key1\" , & value1)]) ; ", - "let handle = recorder . register_mytype (& key) ; ", + "let handle = recorder . register_mytype (& key , & METADATA) ; ", "handle . myop (1) ; ", "} ", "}", @@ -400,6 +493,8 @@ fn test_get_register_and_op_code_op_static_name_dynamic_inline_labels() { #[test] fn test_get_register_and_op_code_op_static_name_existing_labels() { let stream = get_register_and_op_code( + None, + None, "mytype", parse_quote! {"mykeyname"}, Some(Labels::Existing(parse_quote! { mylabels })), @@ -409,9 +504,10 @@ fn test_get_register_and_op_code_op_static_name_existing_labels() { let expected = concat!( "{ ", "static METRIC_NAME : & 'static str = \"mykeyname\" ; ", + "static METADATA : :: metrics :: Metadata < 'static > = :: metrics :: Metadata :: new (module_path ! () , :: metrics :: Level :: INFO , Some (module_path ! ()) ,) ; ", "if let Some (recorder) = :: metrics :: try_recorder () { ", "let key = :: metrics :: Key :: from_parts (METRIC_NAME , mylabels) ; ", - "let handle = recorder . register_mytype (& key) ; ", + "let handle = recorder . register_mytype (& key , & METADATA) ; ", "handle . myop (1) ; ", "} ", "}", @@ -423,6 +519,8 @@ fn test_get_register_and_op_code_op_static_name_existing_labels() { #[test] fn test_get_register_and_op_code_op_owned_name_no_labels() { let stream = get_register_and_op_code( + None, + None, "mytype", parse_quote! { String::from("owned") }, None, @@ -431,9 +529,10 @@ fn test_get_register_and_op_code_op_owned_name_no_labels() { let expected = concat!( "{ ", + "static METADATA : :: metrics :: Metadata < 'static > = :: metrics :: Metadata :: new (module_path ! () , :: metrics :: Level :: INFO , Some (module_path ! ()) ,) ; ", "if let Some (recorder) = :: metrics :: try_recorder () { ", "let key = :: metrics :: Key :: from_name (String :: from (\"owned\")) ; ", - "let handle = recorder . register_mytype (& key) ; ", + "let handle = recorder . register_mytype (& key , & METADATA) ; ", "handle . myop (1) ; ", "} ", "}", @@ -446,6 +545,8 @@ fn test_get_register_and_op_code_op_owned_name_no_labels() { fn test_get_register_and_op_code_op_owned_name_static_inline_labels() { let labels = Labels::Inline(vec![(parse_quote! { "key1" }, parse_quote! { "value1" })]); let stream = get_register_and_op_code( + None, + None, "mytype", parse_quote! { String::from("owned") }, Some(labels), @@ -455,9 +556,10 @@ fn test_get_register_and_op_code_op_owned_name_static_inline_labels() { let expected = concat!( "{ ", "static METRIC_LABELS : [:: metrics :: Label ; 1usize] = [:: metrics :: Label :: from_static_parts (\"key1\" , \"value1\")] ; ", + "static METADATA : :: metrics :: Metadata < 'static > = :: metrics :: Metadata :: new (module_path ! () , :: metrics :: Level :: INFO , Some (module_path ! ()) ,) ; ", "if let Some (recorder) = :: metrics :: try_recorder () { ", "let key = :: metrics :: Key :: from_static_labels (String :: from (\"owned\") , & METRIC_LABELS) ; ", - "let handle = recorder . register_mytype (& key) ; ", + "let handle = recorder . register_mytype (& key , & METADATA) ; ", "handle . myop (1) ; ", "} ", "}", @@ -470,6 +572,8 @@ fn test_get_register_and_op_code_op_owned_name_static_inline_labels() { fn test_get_register_and_op_code_op_owned_name_dynamic_inline_labels() { let labels = Labels::Inline(vec![(parse_quote! { "key1" }, parse_quote! { &value1 })]); let stream = get_register_and_op_code( + None, + None, "mytype", parse_quote! { String::from("owned") }, Some(labels), @@ -478,9 +582,10 @@ fn test_get_register_and_op_code_op_owned_name_dynamic_inline_labels() { let expected = concat!( "{ ", + "static METADATA : :: metrics :: Metadata < 'static > = :: metrics :: Metadata :: new (module_path ! () , :: metrics :: Level :: INFO , Some (module_path ! ()) ,) ; ", "if let Some (recorder) = :: metrics :: try_recorder () { ", "let key = :: metrics :: Key :: from_parts (String :: from (\"owned\") , vec ! [:: metrics :: Label :: new (\"key1\" , & value1)]) ; ", - "let handle = recorder . register_mytype (& key) ; ", + "let handle = recorder . register_mytype (& key , & METADATA) ; ", "handle . myop (1) ; ", "} ", "}", @@ -493,6 +598,8 @@ fn test_get_register_and_op_code_op_owned_name_dynamic_inline_labels() { #[test] fn test_get_register_and_op_code_op_owned_name_existing_labels() { let stream = get_register_and_op_code( + None, + None, "mytype", parse_quote! { String::from("owned") }, Some(Labels::Existing(parse_quote! { mylabels })), @@ -501,9 +608,10 @@ fn test_get_register_and_op_code_op_owned_name_existing_labels() { let expected = concat!( "{ ", + "static METADATA : :: metrics :: Metadata < 'static > = :: metrics :: Metadata :: new (module_path ! () , :: metrics :: Level :: INFO , Some (module_path ! ()) ,) ; ", "if let Some (recorder) = :: metrics :: try_recorder () { ", "let key = :: metrics :: Key :: from_parts (String :: from (\"owned\") , mylabels) ; ", - "let handle = recorder . register_mytype (& key) ; ", + "let handle = recorder . register_mytype (& key , & METADATA) ; ", "handle . myop (1) ; ", "} ", "}", @@ -515,6 +623,8 @@ fn test_get_register_and_op_code_op_owned_name_existing_labels() { #[test] fn test_get_register_and_op_code_op_owned_name_constant_key_labels() { let stream = get_register_and_op_code( + None, + None, "mytype", parse_quote! { String::from("owned") }, Some(Labels::Inline(vec![(parse_quote! { LABEL_KEY }, parse_quote! { "some_val" })])), @@ -523,9 +633,10 @@ fn test_get_register_and_op_code_op_owned_name_constant_key_labels() { let expected = concat!( "{ ", + "static METADATA : :: metrics :: Metadata < 'static > = :: metrics :: Metadata :: new (module_path ! () , :: metrics :: Level :: INFO , Some (module_path ! ()) ,) ; ", "if let Some (recorder) = :: metrics :: try_recorder () { ", "let key = :: metrics :: Key :: from_parts (String :: from (\"owned\") , vec ! [:: metrics :: Label :: new (LABEL_KEY , \"some_val\")]) ; ", - "let handle = recorder . register_mytype (& key) ; ", + "let handle = recorder . register_mytype (& key , & METADATA) ; ", "handle . myop (1) ; ", "} ", "}", diff --git a/metrics-tracing-context/benches/layer.rs b/metrics-tracing-context/benches/layer.rs index 7451c352..892b6668 100644 --- a/metrics-tracing-context/benches/layer.rs +++ b/metrics-tracing-context/benches/layer.rs @@ -15,9 +15,11 @@ fn layer_benchmark(c: &mut Criterion) { static KEY_NAME: &'static str = "key"; static KEY_LABELS: [Label; 1] = [Label::from_static_parts("foo", "bar")]; static KEY_DATA: Key = Key::from_static_parts(&KEY_NAME, &KEY_LABELS); + static METADATA: metrics::Metadata = + metrics::Metadata::new(module_path!(), metrics::Level::INFO, Some(module_path!())); b.iter(|| { - let _ = recorder.register_counter(&KEY_DATA); + let _ = recorder.register_counter(&KEY_DATA, &METADATA); }) }); group.bench_function("no integration", |b| { @@ -33,9 +35,11 @@ fn layer_benchmark(c: &mut Criterion) { static KEY_NAME: &'static str = "key"; static KEY_LABELS: [Label; 1] = [Label::from_static_parts("foo", "bar")]; static KEY_DATA: Key = Key::from_static_parts(&KEY_NAME, &KEY_LABELS); + static METADATA: metrics::Metadata = + metrics::Metadata::new(module_path!(), metrics::Level::INFO, Some(module_path!())); b.iter(|| { - let _ = recorder.register_counter(&KEY_DATA); + let _ = recorder.register_counter(&KEY_DATA, &METADATA); }) }) }); @@ -52,9 +56,11 @@ fn layer_benchmark(c: &mut Criterion) { static KEY_NAME: &'static str = "key"; static KEY_LABELS: [Label; 1] = [Label::from_static_parts("foo", "bar")]; static KEY_DATA: Key = Key::from_static_parts(&KEY_NAME, &KEY_LABELS); + static METADATA: metrics::Metadata = + metrics::Metadata::new(module_path!(), metrics::Level::INFO, Some(module_path!())); b.iter(|| { - let _ = recorder.register_counter(&KEY_DATA); + let _ = recorder.register_counter(&KEY_DATA, &METADATA); }) }) }); @@ -72,9 +78,11 @@ fn layer_benchmark(c: &mut Criterion) { static KEY_NAME: &'static str = "key"; static KEY_LABELS: [Label; 1] = [Label::from_static_parts("foo", "bar")]; static KEY_DATA: Key = Key::from_static_parts(&KEY_NAME, &KEY_LABELS); + static METADATA: metrics::Metadata = + metrics::Metadata::new(module_path!(), metrics::Level::INFO, Some(module_path!())); b.iter(|| { - let _ = recorder.register_counter(&KEY_DATA); + let _ = recorder.register_counter(&KEY_DATA, &METADATA); }) }) }); @@ -92,9 +100,11 @@ fn layer_benchmark(c: &mut Criterion) { static KEY_NAME: &'static str = "key"; static KEY_LABELS: [Label; 1] = [Label::from_static_parts("foo", "bar")]; static KEY_DATA: Key = Key::from_static_parts(&KEY_NAME, &KEY_LABELS); + static METADATA: metrics::Metadata = + metrics::Metadata::new(module_path!(), metrics::Level::INFO, Some(module_path!())); b.iter(|| { - let _ = recorder.register_counter(&KEY_DATA); + let _ = recorder.register_counter(&KEY_DATA, &METADATA); }) }) }); diff --git a/metrics-tracing-context/src/lib.rs b/metrics-tracing-context/src/lib.rs index b43052b0..677630da 100644 --- a/metrics-tracing-context/src/lib.rs +++ b/metrics-tracing-context/src/lib.rs @@ -95,7 +95,9 @@ #![deny(missing_docs)] #![cfg_attr(docsrs, feature(doc_cfg), deny(rustdoc::broken_intra_doc_links))] -use metrics::{Counter, Gauge, Histogram, Key, KeyName, Label, Recorder, SharedString, Unit}; +use metrics::{ + Counter, Gauge, Histogram, Key, KeyName, Label, Metadata, Recorder, SharedString, Unit, +}; use metrics_util::layers::Layer; pub mod label_filter; @@ -217,21 +219,21 @@ where self.inner.describe_histogram(key_name, unit, description) } - fn register_counter(&self, key: &Key) -> Counter { + fn register_counter(&self, key: &Key, metadata: &Metadata<'_>) -> Counter { let new_key = self.enhance_key(key); let key = new_key.as_ref().unwrap_or(key); - self.inner.register_counter(key) + self.inner.register_counter(key, metadata) } - fn register_gauge(&self, key: &Key) -> Gauge { + fn register_gauge(&self, key: &Key, metadata: &Metadata<'_>) -> Gauge { let new_key = self.enhance_key(key); let key = new_key.as_ref().unwrap_or(key); - self.inner.register_gauge(key) + self.inner.register_gauge(key, metadata) } - fn register_histogram(&self, key: &Key) -> Histogram { + fn register_histogram(&self, key: &Key, metadata: &Metadata<'_>) -> Histogram { let new_key = self.enhance_key(key); let key = new_key.as_ref().unwrap_or(key); - self.inner.register_histogram(key) + self.inner.register_histogram(key, metadata) } } diff --git a/metrics-util/benches/filter.rs b/metrics-util/benches/filter.rs index e2b97515..402b24be 100644 --- a/metrics-util/benches/filter.rs +++ b/metrics-util/benches/filter.rs @@ -18,9 +18,11 @@ fn layer_benchmark(c: &mut Criterion) { static KEY_NAME: &'static str = "tokio.foo"; static KEY_LABELS: [Label; 1] = [Label::from_static_parts("foo", "bar")]; static KEY_DATA: Key = Key::from_static_parts(&KEY_NAME, &KEY_LABELS); + static METADATA: metrics::Metadata = + metrics::Metadata::new(module_path!(), metrics::Level::INFO, Some(module_path!())); b.iter(|| { - let _ = recorder.register_counter(&KEY_DATA); + let _ = recorder.register_counter(&KEY_DATA, &METADATA); }) }); group.bench_function("no match", |b| { @@ -30,9 +32,11 @@ fn layer_benchmark(c: &mut Criterion) { static KEY_NAME: &'static str = "hyper.foo"; static KEY_LABELS: [Label; 1] = [Label::from_static_parts("foo", "bar")]; static KEY_DATA: Key = Key::from_static_parts(&KEY_NAME, &KEY_LABELS); + static METADATA: metrics::Metadata = + metrics::Metadata::new(module_path!(), metrics::Level::INFO, Some(module_path!())); b.iter(|| { - let _ = recorder.register_counter(&KEY_DATA); + let _ = recorder.register_counter(&KEY_DATA, &METADATA); }) }); group.bench_function("noop recorder overhead (increment_counter)", |b| { @@ -40,9 +44,11 @@ fn layer_benchmark(c: &mut Criterion) { static KEY_NAME: &'static str = "tokio.foo"; static KEY_LABELS: [Label; 1] = [Label::from_static_parts("foo", "bar")]; static KEY_DATA: Key = Key::from_static_parts(&KEY_NAME, &KEY_LABELS); + static METADATA: metrics::Metadata = + metrics::Metadata::new(module_path!(), metrics::Level::INFO, Some(module_path!())); b.iter(|| { - let _ = recorder.register_counter(&KEY_DATA); + let _ = recorder.register_counter(&KEY_DATA, &METADATA); }) }); } diff --git a/metrics-util/benches/prefix.rs b/metrics-util/benches/prefix.rs index 1bf32cb0..ce2beb3a 100644 --- a/metrics-util/benches/prefix.rs +++ b/metrics-util/benches/prefix.rs @@ -10,9 +10,11 @@ fn layer_benchmark(c: &mut Criterion) { static KEY_NAME: &'static str = "simple_key"; static KEY_LABELS: [Label; 1] = [Label::from_static_parts("foo", "bar")]; static KEY_DATA: Key = Key::from_static_parts(&KEY_NAME, &KEY_LABELS); + static METADATA: metrics::Metadata = + metrics::Metadata::new(module_path!(), metrics::Level::INFO, Some(module_path!())); b.iter(|| { - let _ = recorder.register_counter(&KEY_DATA); + let _ = recorder.register_counter(&KEY_DATA, &METADATA); }) }); group.bench_function("noop recorder overhead (increment_counter)", |b| { @@ -20,9 +22,11 @@ fn layer_benchmark(c: &mut Criterion) { static KEY_NAME: &'static str = "simple_key"; static KEY_LABELS: [Label; 1] = [Label::from_static_parts("foo", "bar")]; static KEY_DATA: Key = Key::from_static_parts(&KEY_NAME, &KEY_LABELS); + static METADATA: metrics::Metadata = + metrics::Metadata::new(module_path!(), metrics::Level::INFO, Some(module_path!())); b.iter(|| { - let _ = recorder.register_counter(&KEY_DATA); + let _ = recorder.register_counter(&KEY_DATA, &METADATA); }) }); group.finish(); diff --git a/metrics-util/benches/router.rs b/metrics-util/benches/router.rs index 41942a96..5714108c 100644 --- a/metrics-util/benches/router.rs +++ b/metrics-util/benches/router.rs @@ -9,9 +9,11 @@ fn layer_benchmark(c: &mut Criterion) { group.bench_function("default target (via mask)", |b| { let recorder = RouterBuilder::from_recorder(NoopRecorder).build(); let key = Key::from_name("test_key"); + static METADATA: metrics::Metadata = + metrics::Metadata::new(module_path!(), metrics::Level::INFO, Some(module_path!())); b.iter(|| { - let _ = recorder.register_counter(&key); + let _ = recorder.register_counter(&key, &METADATA); }) }); group.bench_function("default target (via fallback)", |b| { @@ -19,9 +21,11 @@ fn layer_benchmark(c: &mut Criterion) { builder.add_route(MetricKindMask::COUNTER, "override", NoopRecorder); let recorder = builder.build(); let key = Key::from_name("normal_key"); + static METADATA: metrics::Metadata = + metrics::Metadata::new(module_path!(), metrics::Level::INFO, Some(module_path!())); b.iter(|| { - let _ = recorder.register_counter(&key); + let _ = recorder.register_counter(&key, &METADATA); }) }); group.bench_function("routed target", |b| { @@ -29,9 +33,11 @@ fn layer_benchmark(c: &mut Criterion) { builder.add_route(MetricKindMask::COUNTER, "override", NoopRecorder); let recorder = builder.build(); let key = Key::from_name("override_key"); + static METADATA: metrics::Metadata = + metrics::Metadata::new(module_path!(), metrics::Level::INFO, Some(module_path!())); b.iter(|| { - let _ = recorder.register_counter(&key); + let _ = recorder.register_counter(&key, &METADATA); }) }); } diff --git a/metrics-util/src/debugging.rs b/metrics-util/src/debugging.rs index 96e6e4be..b7f88566 100644 --- a/metrics-util/src/debugging.rs +++ b/metrics-util/src/debugging.rs @@ -19,7 +19,7 @@ use crate::{ }; use indexmap::IndexMap; -use metrics::{Counter, Gauge, Histogram, Key, KeyName, Recorder, SharedString, Unit}; +use metrics::{Counter, Gauge, Histogram, Key, KeyName, Metadata, Recorder, SharedString, Unit}; use ordered_float::OrderedFloat; thread_local! { @@ -292,7 +292,7 @@ impl Recorder for DebuggingRecorder { self.describe_metric(ckey, unit, description); } - fn register_counter(&self, key: &Key) -> Counter { + fn register_counter(&self, key: &Key, _metadata: &Metadata<'_>) -> Counter { let ckey = CompositeKey::new(MetricKind::Counter, key.clone()); self.track_metric(ckey); @@ -313,7 +313,7 @@ impl Recorder for DebuggingRecorder { } } - fn register_gauge(&self, key: &Key) -> Gauge { + fn register_gauge(&self, key: &Key, _metadata: &Metadata<'_>) -> Gauge { let ckey = CompositeKey::new(MetricKind::Gauge, key.clone()); self.track_metric(ckey); @@ -334,7 +334,7 @@ impl Recorder for DebuggingRecorder { } } - fn register_histogram(&self, key: &Key) -> Histogram { + fn register_histogram(&self, key: &Key, _metadata: &Metadata<'_>) -> Histogram { let ckey = CompositeKey::new(MetricKind::Histogram, key.clone()); self.track_metric(ckey); diff --git a/metrics-util/src/layers/fanout.rs b/metrics-util/src/layers/fanout.rs index 0efc9503..430b61d6 100644 --- a/metrics-util/src/layers/fanout.rs +++ b/metrics-util/src/layers/fanout.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use metrics::{ - Counter, CounterFn, Gauge, GaugeFn, Histogram, HistogramFn, Key, KeyName, Recorder, + Counter, CounterFn, Gauge, GaugeFn, Histogram, HistogramFn, Key, KeyName, Metadata, Recorder, SharedString, Unit, }; @@ -119,22 +119,29 @@ impl Recorder for Fanout { } } - fn register_counter(&self, key: &Key) -> Counter { - let counters = - self.recorders.iter().map(|recorder| recorder.register_counter(key)).collect(); + fn register_counter(&self, key: &Key, metadata: &Metadata<'_>) -> Counter { + let counters = self + .recorders + .iter() + .map(|recorder| recorder.register_counter(key, metadata)) + .collect(); FanoutCounter::from_counters(counters).into() } - fn register_gauge(&self, key: &Key) -> Gauge { - let gauges = self.recorders.iter().map(|recorder| recorder.register_gauge(key)).collect(); + fn register_gauge(&self, key: &Key, metadata: &Metadata<'_>) -> Gauge { + let gauges = + self.recorders.iter().map(|recorder| recorder.register_gauge(key, metadata)).collect(); FanoutGauge::from_gauges(gauges).into() } - fn register_histogram(&self, key: &Key) -> Histogram { - let histograms = - self.recorders.iter().map(|recorder| recorder.register_histogram(key)).collect(); + fn register_histogram(&self, key: &Key, metadata: &Metadata<'_>) -> Histogram { + let histograms = self + .recorders + .iter() + .map(|recorder| recorder.register_histogram(key, metadata)) + .collect(); FanoutHistogram::from_histograms(histograms).into() } @@ -170,6 +177,9 @@ mod tests { use crate::test_util::*; use metrics::{Counter, Gauge, Histogram, Unit}; + static METADATA: metrics::Metadata = + metrics::Metadata::new(module_path!(), metrics::Level::INFO, Some(module_path!())); + #[test] fn test_basic_functionality() { let operations = vec![ @@ -188,9 +198,13 @@ mod tests { Some(Unit::Nanoseconds), "histogram desc".into(), ), - RecorderOperation::RegisterCounter("counter_key".into(), Counter::noop()), - RecorderOperation::RegisterGauge("gauge_key".into(), Gauge::noop()), - RecorderOperation::RegisterHistogram("histogram_key".into(), Histogram::noop()), + RecorderOperation::RegisterCounter("counter_key".into(), Counter::noop(), &METADATA), + RecorderOperation::RegisterGauge("gauge_key".into(), Gauge::noop(), &METADATA), + RecorderOperation::RegisterHistogram( + "histogram_key".into(), + Histogram::noop(), + &METADATA, + ), ]; let recorder1 = MockBasicRecorder::from_operations(operations.clone()); diff --git a/metrics-util/src/layers/filter.rs b/metrics-util/src/layers/filter.rs index bfe38665..f7125605 100644 --- a/metrics-util/src/layers/filter.rs +++ b/metrics-util/src/layers/filter.rs @@ -1,6 +1,6 @@ use crate::layers::Layer; use aho_corasick::{AhoCorasick, AhoCorasickBuilder, AhoCorasickKind}; -use metrics::{Counter, Gauge, Histogram, Key, KeyName, Recorder, SharedString, Unit}; +use metrics::{Counter, Gauge, Histogram, Key, KeyName, Metadata, Recorder, SharedString, Unit}; /// Filters and discards metrics matching certain name patterns. /// @@ -38,25 +38,25 @@ impl Recorder for Filter { self.inner.describe_histogram(key_name, unit, description) } - fn register_counter(&self, key: &Key) -> Counter { + fn register_counter(&self, key: &Key, metadata: &Metadata<'_>) -> Counter { if self.should_filter(key.name()) { return Counter::noop(); } - self.inner.register_counter(key) + self.inner.register_counter(key, metadata) } - fn register_gauge(&self, key: &Key) -> Gauge { + fn register_gauge(&self, key: &Key, metadata: &Metadata<'_>) -> Gauge { if self.should_filter(key.name()) { return Gauge::noop(); } - self.inner.register_gauge(key) + self.inner.register_gauge(key, metadata) } - fn register_histogram(&self, key: &Key) -> Histogram { + fn register_histogram(&self, key: &Key, metadata: &Metadata<'_>) -> Histogram { if self.should_filter(key.name()) { return Histogram::noop(); } - self.inner.register_histogram(key) + self.inner.register_histogram(key, metadata) } } @@ -157,6 +157,9 @@ mod tests { use crate::{layers::Layer, test_util::*}; use metrics::{Counter, Gauge, Histogram, Unit}; + static METADATA: metrics::Metadata = + metrics::Metadata::new(module_path!(), metrics::Level::INFO, Some(module_path!())); + #[test] fn test_basic_functionality() { let inputs = vec![ @@ -185,14 +188,19 @@ mod tests { Some(Unit::Count), "gauge desc".into(), ), - RecorderOperation::RegisterCounter("tokio.loops".into(), Counter::noop()), - RecorderOperation::RegisterGauge("hyper.bytes_read".into(), Gauge::noop()), + RecorderOperation::RegisterCounter("tokio.loops".into(), Counter::noop(), &METADATA), + RecorderOperation::RegisterGauge("hyper.bytes_read".into(), Gauge::noop(), &METADATA), RecorderOperation::RegisterHistogram( "hyper.response_latency".into(), Histogram::noop(), + &METADATA, + ), + RecorderOperation::RegisterCounter( + "tokio.spurious_wakeups".into(), + Counter::noop(), + &METADATA, ), - RecorderOperation::RegisterCounter("tokio.spurious_wakeups".into(), Counter::noop()), - RecorderOperation::RegisterGauge("bb8.pooled_conns".into(), Gauge::noop()), + RecorderOperation::RegisterGauge("bb8.pooled_conns".into(), Gauge::noop(), &METADATA), ]; let expectations = vec![ @@ -206,10 +214,11 @@ mod tests { Some(Unit::Nanoseconds), "histogram desc".into(), ), - RecorderOperation::RegisterGauge("hyper.bytes_read".into(), Gauge::noop()), + RecorderOperation::RegisterGauge("hyper.bytes_read".into(), Gauge::noop(), &METADATA), RecorderOperation::RegisterHistogram( "hyper.response_latency".into(), Histogram::noop(), + &METADATA, ), ]; @@ -250,14 +259,19 @@ mod tests { Some(Unit::Count), "gauge desc".into(), ), - RecorderOperation::RegisterCounter("tokiO.loops".into(), Counter::noop()), - RecorderOperation::RegisterGauge("hyper.bytes_read".into(), Gauge::noop()), + RecorderOperation::RegisterCounter("tokiO.loops".into(), Counter::noop(), &METADATA), + RecorderOperation::RegisterGauge("hyper.bytes_read".into(), Gauge::noop(), &METADATA), RecorderOperation::RegisterHistogram( "hyper.response_latency".into(), Histogram::noop(), + &METADATA, + ), + RecorderOperation::RegisterCounter( + "Tokio.spurious_wakeups".into(), + Counter::noop(), + &METADATA, ), - RecorderOperation::RegisterCounter("Tokio.spurious_wakeups".into(), Counter::noop()), - RecorderOperation::RegisterGauge("bB8.pooled_conns".into(), Gauge::noop()), + RecorderOperation::RegisterGauge("bB8.pooled_conns".into(), Gauge::noop(), &METADATA), ]; let expectations = vec![ @@ -271,10 +285,11 @@ mod tests { Some(Unit::Nanoseconds), "histogram desc".into(), ), - RecorderOperation::RegisterGauge("hyper.bytes_read".into(), Gauge::noop()), + RecorderOperation::RegisterGauge("hyper.bytes_read".into(), Gauge::noop(), &METADATA), RecorderOperation::RegisterHistogram( "hyper.response_latency".into(), Histogram::noop(), + &METADATA, ), ]; diff --git a/metrics-util/src/layers/mod.rs b/metrics-util/src/layers/mod.rs index fce92046..bddafc5d 100644 --- a/metrics-util/src/layers/mod.rs +++ b/metrics-util/src/layers/mod.rs @@ -8,7 +8,7 @@ //! Here's an example of a layer that filters out all metrics that start with a specific string: //! //! ```rust -//! # use metrics::{Counter, Gauge, Histogram, Key, KeyName, Recorder, SharedString, Unit}; +//! # use metrics::{Counter, Gauge, Histogram, Key, KeyName, Metadata, Recorder, SharedString, Unit}; //! # use metrics::NoopRecorder as BasicRecorder; //! # use metrics_util::layers::{Layer, Stack, PrefixLayer}; //! // A simple layer that denies any metrics that have "stairway" or "heaven" in their name. @@ -53,25 +53,25 @@ //! self.0.describe_histogram(key_name, unit, description) //! } //! -//! fn register_counter(&self, key: &Key) -> Counter { +//! fn register_counter(&self, key: &Key, metadata: &Metadata<'_>) -> Counter { //! if self.is_invalid_key(key.name()) { //! return Counter::noop(); //! } -//! self.0.register_counter(key) +//! self.0.register_counter(key, metadata) //! } //! -//! fn register_gauge(&self, key: &Key) -> Gauge { +//! fn register_gauge(&self, key: &Key, metadata: &Metadata<'_>) -> Gauge { //! if self.is_invalid_key(key.name()) { //! return Gauge::noop(); //! } -//! self.0.register_gauge(key) +//! self.0.register_gauge(key, metadata) //! } //! -//! fn register_histogram(&self, key: &Key) -> Histogram { +//! fn register_histogram(&self, key: &Key, metadata: &Metadata<'_>) -> Histogram { //! if self.is_invalid_key(key.name()) { //! return Histogram::noop(); //! } -//! self.0.register_histogram(key) +//! self.0.register_histogram(key, metadata) //! } //! } //! @@ -111,7 +111,7 @@ //! .expect("failed to install stack"); //! # } //! ``` -use metrics::{Counter, Gauge, Histogram, Key, KeyName, Recorder, SharedString, Unit}; +use metrics::{Counter, Gauge, Histogram, Key, KeyName, Metadata, Recorder, SharedString, Unit}; use metrics::SetRecorderError; @@ -179,15 +179,15 @@ impl Recorder for Stack { self.inner.describe_histogram(key_name, unit, description); } - fn register_counter(&self, key: &Key) -> Counter { - self.inner.register_counter(key) + fn register_counter(&self, key: &Key, metadata: &Metadata<'_>) -> Counter { + self.inner.register_counter(key, metadata) } - fn register_gauge(&self, key: &Key) -> Gauge { - self.inner.register_gauge(key) + fn register_gauge(&self, key: &Key, metadata: &Metadata<'_>) -> Gauge { + self.inner.register_gauge(key, metadata) } - fn register_histogram(&self, key: &Key) -> Histogram { - self.inner.register_histogram(key) + fn register_histogram(&self, key: &Key, metadata: &Metadata<'_>) -> Histogram { + self.inner.register_histogram(key, metadata) } } diff --git a/metrics-util/src/layers/prefix.rs b/metrics-util/src/layers/prefix.rs index d19171af..6c4f3829 100644 --- a/metrics-util/src/layers/prefix.rs +++ b/metrics-util/src/layers/prefix.rs @@ -1,5 +1,5 @@ use crate::layers::Layer; -use metrics::{Counter, Gauge, Histogram, Key, KeyName, Recorder, SharedString, Unit}; +use metrics::{Counter, Gauge, Histogram, Key, KeyName, Metadata, Recorder, SharedString, Unit}; /// Applies a prefix to every metric key. /// @@ -45,19 +45,19 @@ impl Recorder for Prefix { self.inner.describe_histogram(new_key_name, unit, description) } - fn register_counter(&self, key: &Key) -> Counter { + fn register_counter(&self, key: &Key, metadata: &Metadata<'_>) -> Counter { let new_key = self.prefix_key(key); - self.inner.register_counter(&new_key) + self.inner.register_counter(&new_key, metadata) } - fn register_gauge(&self, key: &Key) -> Gauge { + fn register_gauge(&self, key: &Key, metadata: &Metadata<'_>) -> Gauge { let new_key = self.prefix_key(key); - self.inner.register_gauge(&new_key) + self.inner.register_gauge(&new_key, metadata) } - fn register_histogram(&self, key: &Key) -> Histogram { + fn register_histogram(&self, key: &Key, metadata: &Metadata<'_>) -> Histogram { let new_key = self.prefix_key(key); - self.inner.register_histogram(&new_key) + self.inner.register_histogram(&new_key, metadata) } } @@ -88,6 +88,9 @@ mod tests { use crate::test_util::*; use metrics::{Counter, Gauge, Histogram, Key, KeyName, Unit}; + static METADATA: metrics::Metadata = + metrics::Metadata::new(module_path!(), metrics::Level::INFO, Some(module_path!())); + #[test] fn test_basic_functionality() { let inputs = vec![ @@ -106,9 +109,13 @@ mod tests { Some(Unit::Nanoseconds), "histogram desc".into(), ), - RecorderOperation::RegisterCounter("counter_key".into(), Counter::noop()), - RecorderOperation::RegisterGauge("gauge_key".into(), Gauge::noop()), - RecorderOperation::RegisterHistogram("histogram_key".into(), Histogram::noop()), + RecorderOperation::RegisterCounter("counter_key".into(), Counter::noop(), &METADATA), + RecorderOperation::RegisterGauge("gauge_key".into(), Gauge::noop(), &METADATA), + RecorderOperation::RegisterHistogram( + "histogram_key".into(), + Histogram::noop(), + &METADATA, + ), ]; let expectations = vec![ @@ -127,9 +134,17 @@ mod tests { Some(Unit::Nanoseconds), "histogram desc".into(), ), - RecorderOperation::RegisterCounter("testing.counter_key".into(), Counter::noop()), - RecorderOperation::RegisterGauge("testing.gauge_key".into(), Gauge::noop()), - RecorderOperation::RegisterHistogram("testing.histogram_key".into(), Histogram::noop()), + RecorderOperation::RegisterCounter( + "testing.counter_key".into(), + Counter::noop(), + &METADATA, + ), + RecorderOperation::RegisterGauge("testing.gauge_key".into(), Gauge::noop(), &METADATA), + RecorderOperation::RegisterHistogram( + "testing.histogram_key".into(), + Histogram::noop(), + &METADATA, + ), ]; let recorder = MockBasicRecorder::from_operations(expectations); diff --git a/metrics-util/src/layers/router.rs b/metrics-util/src/layers/router.rs index 87947495..867049d1 100644 --- a/metrics-util/src/layers/router.rs +++ b/metrics-util/src/layers/router.rs @@ -1,4 +1,4 @@ -use metrics::{Counter, Gauge, Histogram, Key, KeyName, Recorder, SharedString, Unit}; +use metrics::{Counter, Gauge, Histogram, Key, KeyName, Metadata, Recorder, SharedString, Unit}; use radix_trie::{Trie, TrieCommon}; use crate::{MetricKind, MetricKindMask}; @@ -54,19 +54,19 @@ impl Recorder for Router { target.describe_histogram(key_name, unit, description) } - fn register_counter(&self, key: &Key) -> Counter { + fn register_counter(&self, key: &Key, metadata: &Metadata<'_>) -> Counter { let target = self.route(MetricKind::Counter, key.name(), &self.counter_routes); - target.register_counter(key) + target.register_counter(key, metadata) } - fn register_gauge(&self, key: &Key) -> Gauge { + fn register_gauge(&self, key: &Key, metadata: &Metadata<'_>) -> Gauge { let target = self.route(MetricKind::Gauge, key.name(), &self.gauge_routes); - target.register_gauge(key) + target.register_gauge(key, metadata) } - fn register_histogram(&self, key: &Key) -> Histogram { + fn register_histogram(&self, key: &Key, metadata: &Metadata<'_>) -> Histogram { let target = self.route(MetricKind::Histogram, key.name(), &self.histogram_routes); - target.register_histogram(key) + target.register_histogram(key, metadata) } } @@ -161,12 +161,18 @@ impl RouterBuilder { #[cfg(test)] mod tests { - use mockall::{mock, predicate::eq, Sequence}; + use mockall::{ + mock, + predicate::{always, eq}, + Sequence, + }; use std::borrow::Cow; use super::RouterBuilder; use crate::MetricKindMask; - use metrics::{Counter, Gauge, Histogram, Key, KeyName, Recorder, SharedString, Unit}; + use metrics::{ + Counter, Gauge, Histogram, Key, KeyName, Metadata, Recorder, SharedString, Unit, + }; mock! { pub TestRecorder { @@ -176,9 +182,9 @@ mod tests { fn describe_counter(&self, key_name: KeyName, unit: Option, description: SharedString); fn describe_gauge(&self, key_name: KeyName, unit: Option, description: SharedString); fn describe_histogram(&self, key_name: KeyName, unit: Option, description: SharedString); - fn register_counter(&self, key: &Key) -> Counter; - fn register_gauge(&self, key: &Key) -> Gauge; - fn register_histogram(&self, key: &Key) -> Histogram; + fn register_counter<'a>(&'a self, key: &'a Key, metadata: &'a Metadata<'a>) -> Counter; + fn register_gauge<'a>(&'a self, key: &'a Key, metadata: &'a Metadata<'a>) -> Gauge; + fn register_histogram<'a>(&'a self, key: &'a Key, metadata: &'a Metadata<'a>) -> Histogram; } } @@ -215,33 +221,36 @@ mod tests { let mut seq = Sequence::new(); + static METADATA: metrics::Metadata = + metrics::Metadata::new(module_path!(), metrics::Level::INFO, Some(module_path!())); + default_mock .expect_register_counter() .times(1) .in_sequence(&mut seq) - .with(eq(default_counter.clone())) - .returning(|_| Counter::noop()); + .with(eq(default_counter.clone()), always()) + .returning(|_, _| Counter::noop()); counter_mock .expect_register_counter() .times(1) .in_sequence(&mut seq) - .with(eq(override_counter.clone())) - .returning(|_| Counter::noop()); + .with(eq(override_counter.clone()), always()) + .returning(|_, _| Counter::noop()); all_mock .expect_register_counter() .times(1) .in_sequence(&mut seq) - .with(eq(all_override.clone())) - .returning(|_| Counter::noop()); + .with(eq(all_override.clone()), always()) + .returning(|_, _| Counter::noop()); all_mock .expect_register_histogram() .times(1) .in_sequence(&mut seq) - .with(eq(all_override.clone())) - .returning(|_| Histogram::noop()); + .with(eq(all_override.clone()), always()) + .returning(|_, _| Histogram::noop()); let mut builder = RouterBuilder::from_recorder(default_mock); builder.add_route(MetricKindMask::COUNTER, "counter_override", counter_mock).add_route( @@ -251,9 +260,9 @@ mod tests { ); let recorder = builder.build(); - let _ = recorder.register_counter(&default_counter); - let _ = recorder.register_counter(&override_counter); - let _ = recorder.register_counter(&all_override); - let _ = recorder.register_histogram(&all_override); + let _ = recorder.register_counter(&default_counter, &METADATA); + let _ = recorder.register_counter(&override_counter, &METADATA); + let _ = recorder.register_counter(&all_override, &METADATA); + let _ = recorder.register_histogram(&all_override, &METADATA); } } diff --git a/metrics-util/src/recoverable.rs b/metrics-util/src/recoverable.rs index d8133e5e..13471025 100644 --- a/metrics-util/src/recoverable.rs +++ b/metrics-util/src/recoverable.rs @@ -1,7 +1,8 @@ use std::sync::{Arc, Weak}; use metrics::{ - Counter, Gauge, Histogram, Key, KeyName, Recorder, SetRecorderError, SharedString, Unit, + Counter, Gauge, Histogram, Key, KeyName, Metadata, Recorder, SetRecorderError, SharedString, + Unit, }; /// Wraps a recorder to allow for recovering it after being installed. @@ -92,25 +93,25 @@ impl Recorder for WeakRecorder { } } - fn register_counter(&self, key: &Key) -> Counter { + fn register_counter(&self, key: &Key, metadata: &Metadata<'_>) -> Counter { if let Some(recorder) = self.recorder.upgrade() { - recorder.register_counter(key) + recorder.register_counter(key, metadata) } else { Counter::noop() } } - fn register_gauge(&self, key: &Key) -> Gauge { + fn register_gauge(&self, key: &Key, metadata: &Metadata<'_>) -> Gauge { if let Some(recorder) = self.recorder.upgrade() { - recorder.register_gauge(key) + recorder.register_gauge(key, metadata) } else { Gauge::noop() } } - fn register_histogram(&self, key: &Key) -> Histogram { + fn register_histogram(&self, key: &Key, metadata: &Metadata<'_>) -> Histogram { if let Some(recorder) = self.recorder.upgrade() { - recorder.register_histogram(key) + recorder.register_histogram(key, metadata) } else { Histogram::noop() } @@ -226,15 +227,15 @@ mod tests { todo!() } - fn register_counter(&self, _: &Key) -> Counter { + fn register_counter(&self, _: &Key, _: &Metadata<'_>) -> Counter { Counter::from_arc(Arc::clone(&self.counter)) } - fn register_gauge(&self, _: &Key) -> Gauge { + fn register_gauge(&self, _: &Key, _: &Metadata<'_>) -> Gauge { Gauge::from_arc(Arc::clone(&self.gauge)) } - fn register_histogram(&self, _: &Key) -> Histogram { + fn register_histogram(&self, _: &Key, _: &Metadata<'_>) -> Histogram { Histogram::from_arc(Arc::clone(&self.histogram)) } } diff --git a/metrics-util/src/test_util.rs b/metrics-util/src/test_util.rs index 94611d90..cae3fc1d 100644 --- a/metrics-util/src/test_util.rs +++ b/metrics-util/src/test_util.rs @@ -1,7 +1,7 @@ -use metrics::{Counter, Gauge, Histogram, Key, KeyName, Recorder, SharedString, Unit}; +use metrics::{Counter, Gauge, Histogram, Key, KeyName, Metadata, Recorder, SharedString, Unit}; use mockall::{ mock, - predicate::{self, eq}, + predicate::{self, always, eq}, Predicate, }; @@ -10,9 +10,9 @@ pub enum RecorderOperation { DescribeCounter(KeyName, Option, SharedString), DescribeGauge(KeyName, Option, SharedString), DescribeHistogram(KeyName, Option, SharedString), - RegisterCounter(Key, Counter), - RegisterGauge(Key, Gauge), - RegisterHistogram(Key, Histogram), + RegisterCounter(Key, Counter, &'static Metadata<'static>), + RegisterGauge(Key, Gauge, &'static Metadata<'static>), + RegisterHistogram(Key, Histogram, &'static Metadata<'static>), } impl RecorderOperation { @@ -27,11 +27,13 @@ impl RecorderOperation { RecorderOperation::DescribeHistogram(key_name, unit, desc) => { expect_describe_histogram(mock, key_name, unit, desc) } - RecorderOperation::RegisterCounter(key, counter) => { + RecorderOperation::RegisterCounter(key, counter, _) => { expect_register_counter(mock, key, counter) } - RecorderOperation::RegisterGauge(key, gauge) => expect_register_gauge(mock, key, gauge), - RecorderOperation::RegisterHistogram(key, histogram) => { + RecorderOperation::RegisterGauge(key, gauge, _) => { + expect_register_gauge(mock, key, gauge) + } + RecorderOperation::RegisterHistogram(key, histogram, _) => { expect_register_histogram(mock, key, histogram) } } @@ -51,14 +53,14 @@ impl RecorderOperation { RecorderOperation::DescribeHistogram(key_name, unit, desc) => { recorder.describe_histogram(key_name, unit, desc); } - RecorderOperation::RegisterCounter(key, _) => { - let _ = recorder.register_counter(&key); + RecorderOperation::RegisterCounter(key, _, metadata) => { + let _ = recorder.register_counter(&key, metadata); } - RecorderOperation::RegisterGauge(key, _) => { - let _ = recorder.register_gauge(&key); + RecorderOperation::RegisterGauge(key, _, metadata) => { + let _ = recorder.register_gauge(&key, metadata); } - RecorderOperation::RegisterHistogram(key, _) => { - let _ = recorder.register_histogram(&key); + RecorderOperation::RegisterHistogram(key, _, metadata) => { + let _ = recorder.register_histogram(&key, metadata); } } } @@ -71,9 +73,9 @@ mock! { fn describe_counter(&self, key_name: KeyName, unit: Option, description: SharedString); fn describe_gauge(&self, key_name: KeyName, unit: Option, description: SharedString); fn describe_histogram(&self, key_name: KeyName, unit: Option, description: SharedString); - fn register_counter(&self, key: &Key) -> Counter; - fn register_gauge(&self, key: &Key) -> Gauge; - fn register_histogram(&self, key: &Key) -> Histogram; + fn register_counter<'a>(&'a self, key: &'a Key, metadata: &'a Metadata<'a>) -> Counter; + fn register_gauge<'a>(&'a self, key: &'a Key, metadata: &'a Metadata<'a>) -> Gauge; + fn register_histogram<'a>(&'a self, key: &'a Key, metadata: &'a Metadata<'a>) -> Histogram; } } @@ -127,15 +129,15 @@ pub fn expect_describe_histogram( } pub fn expect_register_counter(mock: &mut MockBasicRecorder, key: Key, counter: Counter) { - mock.expect_register_counter().times(1).with(ref_eq(key)).return_const(counter); + mock.expect_register_counter().times(1).with(ref_eq(key), always()).return_const(counter); } pub fn expect_register_gauge(mock: &mut MockBasicRecorder, key: Key, gauge: Gauge) { - mock.expect_register_gauge().times(1).with(ref_eq(key)).return_const(gauge); + mock.expect_register_gauge().times(1).with(ref_eq(key), always()).return_const(gauge); } pub fn expect_register_histogram(mock: &mut MockBasicRecorder, key: Key, histogram: Histogram) { - mock.expect_register_histogram().times(1).with(ref_eq(key)).return_const(histogram); + mock.expect_register_histogram().times(1).with(ref_eq(key), always()).return_const(histogram); } fn ref_eq(value: T) -> impl Predicate { diff --git a/metrics/benches/macros.rs b/metrics/benches/macros.rs index ba7a30b3..f0d7feec 100644 --- a/metrics/benches/macros.rs +++ b/metrics/benches/macros.rs @@ -3,7 +3,9 @@ extern crate criterion; use criterion::Criterion; -use metrics::{counter, Counter, Gauge, Histogram, Key, KeyName, Recorder, SharedString, Unit}; +use metrics::{ + counter, Counter, Gauge, Histogram, Key, KeyName, Metadata, Recorder, SharedString, Unit, +}; use rand::{thread_rng, Rng}; #[derive(Default)] @@ -12,13 +14,13 @@ impl Recorder for TestRecorder { fn describe_counter(&self, _: KeyName, _: Option, _: SharedString) {} fn describe_gauge(&self, _: KeyName, _: Option, _: SharedString) {} fn describe_histogram(&self, _: KeyName, _: Option, _: SharedString) {} - fn register_counter(&self, _: &Key) -> Counter { + fn register_counter(&self, _: &Key, _: &Metadata<'_>) -> Counter { Counter::noop() } - fn register_gauge(&self, _: &Key) -> Gauge { + fn register_gauge(&self, _: &Key, _: &Metadata<'_>) -> Gauge { Gauge::noop() } - fn register_histogram(&self, _: &Key) -> Histogram { + fn register_histogram(&self, _: &Key, _: &Metadata<'_>) -> Histogram { Histogram::noop() } } diff --git a/metrics/examples/basic.rs b/metrics/examples/basic.rs index 1fbb3fd2..4dee080e 100644 --- a/metrics/examples/basic.rs +++ b/metrics/examples/basic.rs @@ -10,7 +10,7 @@ use std::sync::Arc; use metrics::{ absolute_counter, counter, decrement_gauge, describe_counter, describe_gauge, describe_histogram, gauge, histogram, increment_counter, increment_gauge, register_counter, - register_gauge, register_histogram, KeyName, SharedString, + register_gauge, register_histogram, KeyName, Metadata, SharedString, }; use metrics::{Counter, CounterFn, Gauge, GaugeFn, Histogram, HistogramFn, Key, Recorder, Unit}; @@ -77,15 +77,15 @@ impl Recorder for PrintRecorder { ); } - fn register_counter(&self, key: &Key) -> Counter { + fn register_counter(&self, key: &Key, _metadata: &Metadata<'_>) -> Counter { Counter::from_arc(Arc::new(PrintHandle(key.clone()))) } - fn register_gauge(&self, key: &Key) -> Gauge { + fn register_gauge(&self, key: &Key, _metadata: &Metadata<'_>) -> Gauge { Gauge::from_arc(Arc::new(PrintHandle(key.clone()))) } - fn register_histogram(&self, key: &Key) -> Histogram { + fn register_histogram(&self, key: &Key, _metadata: &Metadata<'_>) -> Histogram { Histogram::from_arc(Arc::new(PrintHandle(key.clone()))) } } diff --git a/metrics/src/lib.rs b/metrics/src/lib.rs index 93062297..9d23df7c 100644 --- a/metrics/src/lib.rs +++ b/metrics/src/lib.rs @@ -270,6 +270,9 @@ pub use self::key::*; mod label; pub use self::label::*; +mod metadata; +pub use self::metadata::*; + mod recorder; pub use self::recorder::*; @@ -520,11 +523,14 @@ pub use metrics_macros::register_histogram; /// /// # Example /// ``` -/// # use metrics::counter; +/// # use metrics::{counter, Level}; /// # fn main() { /// // A basic counter: /// counter!("some_metric_name", 12); /// +/// // A basic counter with level and target specified: +/// counter!(target: "specific_target", level: Level::DEBUG, "some_metric_name", 12); +/// /// // Specifying labels inline, including using constants for either the key or value: /// counter!("some_metric_name", 12, "service" => "http"); /// @@ -558,11 +564,14 @@ pub use metrics_macros::counter; /// /// # Example /// ``` -/// # use metrics::increment_counter; +/// # use metrics::{increment_counter, Level}; /// # fn main() { /// // A basic increment: /// increment_counter!("some_metric_name"); /// +/// // A basic increment with level and target specified: +/// increment_counter!(target: "specific_target", level: Level::DEBUG, "some_metric_name"); +/// /// // Specifying labels inline, including using constants for either the key or value: /// increment_counter!("some_metric_name", "service" => "http"); /// @@ -603,11 +612,14 @@ pub use metrics_macros::increment_counter; /// /// # Example /// ``` -/// # use metrics::absolute_counter; +/// # use metrics::{absolute_counter, Level}; /// # fn main() { /// // A basic counter: /// absolute_counter!("some_metric_name", 12); /// +/// // A basic counter with level and target specified: +/// absolute_counter!(target: "specific_target", level: Level::DEBUG, "some_metric_name", 12); +/// /// // Specifying labels inline, including using constants for either the key or value: /// absolute_counter!("some_metric_name", 13, "service" => "http"); /// @@ -641,11 +653,14 @@ pub use metrics_macros::absolute_counter; /// /// # Example /// ``` -/// # use metrics::gauge; +/// # use metrics::{gauge, Level}; /// # fn main() { /// // A basic gauge: /// gauge!("some_metric_name", 42.2222); /// +/// // A basic gauge with level and target specified: +/// gauge!(target: "specific_target", level: Level::DEBUG, "some_metric_name", 42.2222); +/// /// // Specifying labels inline, including using constants for either the key or value: /// gauge!("some_metric_name", 66.6666, "service" => "http"); /// @@ -679,11 +694,14 @@ pub use metrics_macros::gauge; /// /// # Example /// ``` -/// # use metrics::increment_gauge; +/// # use metrics::{increment_gauge, Level}; /// # fn main() { /// // A basic gauge: /// increment_gauge!("some_metric_name", 42.2222); /// +/// // A basic gauge with level and target specified: +/// increment_gauge!(target: "specific_target", level: Level::DEBUG, "some_metric_name", 42.2222); +/// /// // Specifying labels inline, including using constants for either the key or value: /// increment_gauge!("some_metric_name", 66.6666, "service" => "http"); /// @@ -717,11 +735,14 @@ pub use metrics_macros::increment_gauge; /// /// # Example /// ``` -/// # use metrics::decrement_gauge; +/// # use metrics::{decrement_gauge, Level}; /// # fn main() { /// // A basic gauge: /// decrement_gauge!("some_metric_name", 42.2222); /// +/// // A basic gauge with level and target specified: +/// decrement_gauge!(target: "specific_target", level: Level::DEBUG, "some_metric_name", 42.2222); +/// /// // Specifying labels inline, including using constants for either the key or value: /// decrement_gauge!("some_metric_name", 66.6666, "service" => "http"); /// @@ -764,12 +785,15 @@ pub use metrics_macros::decrement_gauge; /// /// # Example /// ``` -/// # use metrics::histogram; +/// # use metrics::{histogram, Level}; /// # use std::time::Duration; /// # fn main() { /// // A basic histogram: /// histogram!("some_metric_name", 34.3); /// +/// // A basic histogram with level and target specified: +/// histogram!(target: "specific_target", level: Level::DEBUG, "some_metric_name", 34.3); +/// /// // An implicit conversion from `Duration`: /// let d = Duration::from_millis(17); /// histogram!("some_metric_name", d); diff --git a/metrics/src/metadata.rs b/metrics/src/metadata.rs new file mode 100644 index 00000000..71653e1f --- /dev/null +++ b/metrics/src/metadata.rs @@ -0,0 +1,67 @@ +/// Describes the level of verbosity of a metric event. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Level(LevelInner); + +impl Level { + /// The "error" level. + pub const TRACE: Self = Self(LevelInner::Trace); + /// The "warn" level. + pub const DEBUG: Self = Self(LevelInner::Debug); + /// The "info" level. + pub const INFO: Self = Self(LevelInner::Info); + /// The "debug" level. + pub const WARN: Self = Self(LevelInner::Warn); + /// The "trace" level. + pub const ERROR: Self = Self(LevelInner::Error); +} + +#[derive(Debug, Clone, PartialEq, Eq)] +enum LevelInner { + Trace = 0, + Debug = 1, + Info = 2, + Warn = 3, + Error = 4, +} + +/// Metadata describing a metric event. This provides additional context to [`Recorder`](crate::Recorder), allowing for +/// fine-grained filtering. +/// +/// Contains the following: +/// +/// - A [`target`](Metadata::target), specifying the part of the system where the metric event occurred. When +/// initialized via the [metrics macro], and left unspecified, this defaults to the module path the +/// macro was invoked from. +/// - A [`level`](Metadata::level), specifying the verbosity the metric event is emitted at. +/// - An optional [`module_path`](Metadata::module_path), specifying the the module path the metric event was emitted +/// from. +/// +/// [metrics_macros]: https://docs.rs/metrics/latest/metrics/#macros +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Metadata<'a> { + target: &'a str, + level: Level, + module_path: Option<&'a str>, +} + +impl<'a> Metadata<'a> { + /// Constructs a new [`Metadata`]. + pub const fn new(target: &'a str, level: Level, module_path: Option<&'a str>) -> Self { + Self { target, level, module_path } + } + + /// Returns the verbosity level of the metric event. + pub fn level(&self) -> &Level { + &self.level + } + + /// Returns the target of the metric event. This specifies the part of the system where the event occurred. + pub fn target(&self) -> &'a str { + self.target + } + + /// Returns the module path of the metric event. This specifies the module where the event occurred. + pub fn module_path(&self) -> Option<&'a str> { + self.module_path + } +} diff --git a/metrics/src/recorder.rs b/metrics/src/recorder.rs index 13ae93ec..8c351aee 100644 --- a/metrics/src/recorder.rs +++ b/metrics/src/recorder.rs @@ -1,7 +1,8 @@ use std::fmt; use self::cell::RecorderOnceCell; -use crate::{Counter, Gauge, Histogram, Key, KeyName, SharedString, Unit}; + +use crate::{Counter, Gauge, Histogram, Key, KeyName, Metadata, SharedString, Unit}; mod cell { use super::{Recorder, SetRecorderError}; @@ -119,13 +120,13 @@ pub trait Recorder { fn describe_histogram(&self, key: KeyName, unit: Option, description: SharedString); /// Registers a counter. - fn register_counter(&self, key: &Key) -> Counter; + fn register_counter(&self, key: &Key, metadata: &Metadata<'_>) -> Counter; /// Registers a gauge. - fn register_gauge(&self, key: &Key) -> Gauge; + fn register_gauge(&self, key: &Key, metadata: &Metadata<'_>) -> Gauge; /// Registers a histogram. - fn register_histogram(&self, key: &Key) -> Histogram; + fn register_histogram(&self, key: &Key, metadata: &Metadata<'_>) -> Histogram; } /// A no-op recorder. @@ -138,13 +139,13 @@ impl Recorder for NoopRecorder { fn describe_counter(&self, _key: KeyName, _unit: Option, _description: SharedString) {} fn describe_gauge(&self, _key: KeyName, _unit: Option, _description: SharedString) {} fn describe_histogram(&self, _key: KeyName, _unit: Option, _description: SharedString) {} - fn register_counter(&self, _key: &Key) -> Counter { + fn register_counter(&self, _key: &Key, _metadata: &Metadata<'_>) -> Counter { Counter::noop() } - fn register_gauge(&self, _key: &Key) -> Gauge { + fn register_gauge(&self, _key: &Key, _metadata: &Metadata<'_>) -> Gauge { Gauge::noop() } - fn register_histogram(&self, _key: &Key) -> Histogram { + fn register_histogram(&self, _key: &Key, _metadata: &Metadata<'_>) -> Histogram { Histogram::noop() } }