From 7a8f3da8596779ed75d22343021c3b24370ae497 Mon Sep 17 00:00:00 2001 From: Toby Lawrence Date: Thu, 12 Nov 2020 23:23:32 -0500 Subject: [PATCH] wip --- COPYRIGHT | 146 +++++------ metrics-benchmark/src/main.rs | 4 +- metrics-exporter-prometheus/src/lib.rs | 8 +- metrics-macros/src/lib.rs | 25 +- metrics-macros/src/tests.rs | 69 ++--- metrics-tracing-context/benches/layer.rs | 12 +- metrics-tracing-context/src/lib.rs | 4 +- metrics-tracing-context/tests/integration.rs | 18 +- metrics-util/benches/prefix.rs | 14 +- metrics-util/benches/registry.rs | 18 +- metrics-util/src/layers/prefix.rs | 10 +- metrics/examples/sizes.rs | 17 +- metrics/src/common.rs | 5 +- metrics/src/key.rs | 251 ++++++++----------- metrics/src/lib.rs | 2 + 15 files changed, 288 insertions(+), 315 deletions(-) diff --git a/COPYRIGHT b/COPYRIGHT index b3901ad..191de5c 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,102 +1,94 @@ Short version for non-lawyers: -metrics is MIT licensed. +`metrics` is MIT licensed. Longer version: -Copyrights in the metrics project are retained by their contributors. No -copyright assignment is required to contribute to the metrics project. +Copyrights in the `metrics` project are retained by their contributors. No copyright assignment is +required to contribute to the `metrics` project. -Some files include explicit copyright notices and/or license notices. -For full authorship information, see the version control history. +Some files include explicit copyright notices and/or license notices. For full authorship +information, see the version control history. -Except as otherwise noted (below and/or in individual files), metrics -is licensed under the MIT license or -. +Except as otherwise noted (below and/or in individual files), `metrics` is licensed under the MIT +license or . -metrics includes packages written by third parties. -The following third party packages are included, and carry -their own copyright notices and license terms: +`metrics` includes packages written by third parties. The following third party packages are +included, and carry their own copyright notices and license terms: -* Portions of the API design are derived from tic - , which carries the following - license: +* Portions of the API design are derived from the `tic` crate which carries the following license: Copyright (c) 2016 Brian Martin - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -* metrics is a fork of rust-lang-nursery/log which carries the following - license: +* metrics is a fork of `rust-lang-nursery/log` which carries the following license: Copyright (c) 2014 The Rust Project Developers - Permission is hereby granted, free of charge, to any - person obtaining a copy of this software and associated - documentation files (the "Software"), to deal in the - Software without restriction, including without - limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of - the Software, and to permit persons to whom the Software - is furnished to do so, subject to the following - conditions: + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice - shall be included in all copies or substantial portions - of the Software. + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF - ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED - TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT - SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR - IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -* metrics-observer reuses code from `std::time::Duration` which carries - the following license: +* metrics-observer reuses code from `std::time::Duration` which carries the following license: - Permission is hereby granted, free of charge, to any - person obtaining a copy of this software and associated - documentation files (the "Software"), to deal in the - Software without restriction, including without - limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of - the Software, and to permit persons to whom the Software - is furnished to do so, subject to the following - conditions: + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice - shall be included in all copies or substantial portions - of the Software. + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF - ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED - TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT - SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR - IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. \ No newline at end of file + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + * metrics includes code from the `beef` crate which carries the following license: + + Copyright (c) 2020 Maciej Hirsz + + The MIT License (MIT) + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/metrics-benchmark/src/main.rs b/metrics-benchmark/src/main.rs index 912b6f3..fd9b6f6 100644 --- a/metrics-benchmark/src/main.rs +++ b/metrics-benchmark/src/main.rs @@ -80,7 +80,7 @@ impl Generator { impl Drop for Generator { fn drop(&mut self) { info!( - " sender latency: min: {:9} p50: {:9} p95: {:9} p99: {:9} p999: {:9} max: {:9}", + " sender latency: min: {:8} p50: {:8} p95: {:8} p99: {:8} p999: {:8} max: {:8}", nanos_to_readable(self.hist.min()), nanos_to_readable(self.hist.value_at_percentile(50.0)), nanos_to_readable(self.hist.value_at_percentile(95.0)), @@ -196,7 +196,7 @@ fn main() { info!("--------------------------------------------------------------------------------"); info!(" ingested samples total: {}", total); info!( - "snapshot retrieval: min: {:9} p50: {:9} p95: {:9} p99: {:9} p999: {:9} max: {:9}", + "snapshot retrieval: min: {:8} p50: {:8} p95: {:8} p99: {:8} p999: {:8} max: {:8}", nanos_to_readable(snapshot_hist.min()), nanos_to_readable(snapshot_hist.value_at_percentile(50.0)), nanos_to_readable(snapshot_hist.value_at_percentile(95.0)), diff --git a/metrics-exporter-prometheus/src/lib.rs b/metrics-exporter-prometheus/src/lib.rs index 4657d16..7bf4d99 100644 --- a/metrics-exporter-prometheus/src/lib.rs +++ b/metrics-exporter-prometheus/src/lib.rs @@ -334,7 +334,7 @@ impl PrometheusRecorder { fn add_description_if_missing(&self, key: &Key, description: Option<&'static str>) { if let Some(description) = description { let mut descriptions = self.inner.descriptions.write(); - if !descriptions.contains_key(key.name().as_ref()) { + if !descriptions.contains_key(key.name().to_string().as_str()) { descriptions.insert(key.name().to_string(), description); } } @@ -552,7 +552,11 @@ fn key_to_parts(key: Key) -> (String, Vec) { let name = key.name(); let labels = key.labels(); let sanitize = |c| c == '.' || c == '=' || c == '{' || c == '}' || c == '+' || c == '-'; - let name = name.replace(sanitize, "_"); + let name = name + .parts() + .map(|s| s.replace(sanitize, "_")) + .collect::>() + .join("_"); let labels = labels .into_iter() .map(|label| { diff --git a/metrics-macros/src/lib.rs b/metrics-macros/src/lib.rs index 6309c95..11df453 100644 --- a/metrics-macros/src/lib.rs +++ b/metrics-macros/src/lib.rs @@ -224,13 +224,13 @@ pub fn histogram(input: TokenStream) -> TokenStream { fn get_expanded_registration( metric_type: &str, - key: LitStr, + name: LitStr, unit: Option, description: Option, labels: Option, ) -> proc_macro2::TokenStream { let register_ident = format_ident!("register_{}", metric_type); - let key = key_to_quoted(key, labels); + let key = key_to_quoted(labels); let unit = match unit { Some(e) => quote! { Some(#e) }, @@ -244,6 +244,7 @@ fn get_expanded_registration( quote! { { + static METRIC_NAME: [metrics::SharedString; 1] = [metrics::SharedString::const_str(#name)]; // Only do this work if there's a recorder installed. if let Some(recorder) = metrics::try_recorder() { // Registrations are fairly rare, don't attempt to cache here @@ -257,7 +258,7 @@ fn get_expanded_registration( fn get_expanded_callsite( metric_type: &str, op_type: &str, - key: LitStr, + name: LitStr, labels: Option, op_values: V, ) -> proc_macro2::TokenStream @@ -288,7 +289,7 @@ where let labels_len = quote! { #labels_len }; quote! { - static METRIC_NAME: metrics::NameParts = metrics::NameParts::from_static_name(#key); + static METRIC_NAME: [metrics::SharedString; 1] = [metrics::SharedString::const_str(#name)]; static METRIC_LABELS: [metrics::Label; #labels_len] = [#(#labels),*]; static METRIC_KEY: metrics::KeyData = metrics::KeyData::from_static_parts(&METRIC_NAME, &METRIC_LABELS); @@ -296,7 +297,7 @@ where } None => { quote! { - static METRIC_NAME: metrics::NameParts = metrics::NameParts::from_static_name(#key); + static METRIC_NAME: [metrics::SharedString; 1] = [metrics::SharedString::const_str(#name)]; static METRIC_KEY: metrics::KeyData = metrics::KeyData::from_static_name(&METRIC_NAME); } @@ -316,9 +317,11 @@ where } } else { // We're on the slow path, so we allocate, womp. - let key = key_to_quoted(key, labels); + let key = key_to_quoted(labels); quote! { { + static METRIC_NAME: [metrics::SharedString; 1] = [metrics::SharedString::const_str(#name)]; + // Only do this work if there's a recorder installed. if let Some(recorder) = metrics::try_recorder() { recorder.#op_ident(metrics::Key::Owned(#key), #op_values); @@ -355,17 +358,19 @@ fn read_key(input: &mut ParseStream) -> Result { Ok(key) } -fn key_to_quoted(name: LitStr, labels: Option) -> proc_macro2::TokenStream { +fn key_to_quoted(labels: Option) -> proc_macro2::TokenStream { match labels { - None => quote! { metrics::KeyData::from_name(#name) }, + None => quote! { metrics::KeyData::from_static_name(&METRIC_NAME) }, Some(labels) => match labels { Labels::Inline(pairs) => { let labels = pairs .into_iter() .map(|(key, val)| quote! { metrics::Label::new(#key, #val) }); - quote! { metrics::KeyData::from_parts(#name, vec![#(#labels),*]) } + quote! { + metrics::KeyData::from_hybrid_parts(&METRIC_NAME, vec![#(#labels),*]) + } } - Labels::Existing(e) => quote! { metrics::KeyData::from_parts(#name, #e) }, + Labels::Existing(e) => quote! { metrics::KeyData::from_hybrid_parts(&METRIC_NAME, #e) }, }, } } diff --git a/metrics-macros/src/tests.rs b/metrics-macros/src/tests.rs index cf49d38..66654c6 100644 --- a/metrics-macros/src/tests.rs +++ b/metrics-macros/src/tests.rs @@ -10,9 +10,11 @@ fn test_get_expanded_registration() { get_expanded_registration("mytype", parse_quote! { "mykeyname" }, None, None, None); let expected = concat!( - "{ if let Some (recorder) = metrics :: try_recorder () { ", + "{ ", + "static METRIC_NAME : [metrics :: SharedString ; 1] = [metrics :: SharedString :: const_str (\"mykeyname\")] ; ", + "if let Some (recorder) = metrics :: try_recorder () { ", "recorder . register_mytype (", - "metrics :: Key :: Owned (metrics :: KeyData :: from_name (\"mykeyname\")) , ", + "metrics :: Key :: Owned (metrics :: KeyData :: from_static_name (& METRIC_NAME)) , ", "None , ", "None", ") ; ", @@ -35,9 +37,11 @@ fn test_get_expanded_registration_with_unit() { ); let expected = concat!( - "{ if let Some (recorder) = metrics :: try_recorder () { ", + "{ ", + "static METRIC_NAME : [metrics :: SharedString ; 1] = [metrics :: SharedString :: const_str (\"mykeyname\")] ; ", + "if let Some (recorder) = metrics :: try_recorder () { ", "recorder . register_mytype (", - "metrics :: Key :: Owned (metrics :: KeyData :: from_name (\"mykeyname\")) , ", + "metrics :: Key :: Owned (metrics :: KeyData :: from_static_name (& METRIC_NAME)) , ", "Some (metrics :: Unit :: Nanoseconds) , ", "None", ") ; ", @@ -59,9 +63,11 @@ fn test_get_expanded_registration_with_description() { ); let expected = concat!( - "{ if let Some (recorder) = metrics :: try_recorder () { ", + "{ ", + "static METRIC_NAME : [metrics :: SharedString ; 1] = [metrics :: SharedString :: const_str (\"mykeyname\")] ; ", + "if let Some (recorder) = metrics :: try_recorder () { ", "recorder . register_mytype (", - "metrics :: Key :: Owned (metrics :: KeyData :: from_name (\"mykeyname\")) , ", + "metrics :: Key :: Owned (metrics :: KeyData :: from_static_name (& METRIC_NAME)) , ", "None , ", "Some (\"flerkin\")", ") ; ", @@ -84,9 +90,11 @@ fn test_get_expanded_registration_with_unit_and_description() { ); let expected = concat!( - "{ if let Some (recorder) = metrics :: try_recorder () { ", + "{ ", + "static METRIC_NAME : [metrics :: SharedString ; 1] = [metrics :: SharedString :: const_str (\"mykeyname\")] ; ", + "if let Some (recorder) = metrics :: try_recorder () { ", "recorder . register_mytype (", - "metrics :: Key :: Owned (metrics :: KeyData :: from_name (\"mykeyname\")) , ", + "metrics :: Key :: Owned (metrics :: KeyData :: from_static_name (& METRIC_NAME)) , ", "Some (metrics :: Unit :: Nanoseconds) , ", "Some (\"flerkin\")", ") ; ", @@ -108,7 +116,8 @@ fn test_get_expanded_callsite_fast_path_no_labels() { let expected = concat!( "{ ", - "static METRIC_KEY : metrics :: KeyData = metrics :: KeyData :: from_static_name (\"mykeyname\") ; ", + "static METRIC_NAME : [metrics :: SharedString ; 1] = [metrics :: SharedString :: const_str (\"mykeyname\")] ; ", + "static METRIC_KEY : metrics :: KeyData = metrics :: KeyData :: from_static_name (& METRIC_NAME) ; ", "if let Some (recorder) = metrics :: try_recorder () { ", "recorder . myop_mytype (metrics :: Key :: Borrowed (& METRIC_KEY) , 1) ; ", "} }", @@ -130,8 +139,9 @@ fn test_get_expanded_callsite_fast_path_static_labels() { let expected = concat!( "{ ", + "static METRIC_NAME : [metrics :: SharedString ; 1] = [metrics :: SharedString :: const_str (\"mykeyname\")] ; ", "static METRIC_LABELS : [metrics :: Label ; 1usize] = [metrics :: Label :: from_static_parts (\"key1\" , \"value1\")] ; ", - "static METRIC_KEY : metrics :: KeyData = metrics :: KeyData :: from_static_parts (\"mykeyname\" , & METRIC_LABELS) ; ", + "static METRIC_KEY : metrics :: KeyData = metrics :: KeyData :: from_static_parts (& METRIC_NAME , & METRIC_LABELS) ; ", "if let Some (recorder) = metrics :: try_recorder () { ", "recorder . myop_mytype (metrics :: Key :: Borrowed (& METRIC_KEY) , 1) ; ", "} ", @@ -154,9 +164,10 @@ fn test_get_expanded_callsite_fast_path_dynamic_labels() { let expected = concat!( "{ ", + "static METRIC_NAME : [metrics :: SharedString ; 1] = [metrics :: SharedString :: const_str (\"mykeyname\")] ; ", "if let Some (recorder) = metrics :: try_recorder () { ", "recorder . myop_mytype (metrics :: Key :: Owned (", - "metrics :: KeyData :: from_parts (\"mykeyname\" , vec ! [metrics :: Label :: new (\"key1\" , & value1)])", + "metrics :: KeyData :: from_hybrid_parts (& METRIC_NAME , vec ! [metrics :: Label :: new (\"key1\" , & value1)])", ") , 1) ; ", "} ", "}", @@ -178,9 +189,10 @@ fn test_get_expanded_callsite_regular_path() { let expected = concat!( "{ ", + "static METRIC_NAME : [metrics :: SharedString ; 1] = [metrics :: SharedString :: const_str (\"mykeyname\")] ; ", "if let Some (recorder) = metrics :: try_recorder () { ", "recorder . myop_mytype (", - "metrics :: Key :: Owned (metrics :: KeyData :: from_parts (\"mykeyname\" , mylabels)) , ", + "metrics :: Key :: Owned (metrics :: KeyData :: from_hybrid_parts (& METRIC_NAME , mylabels)) , ", "1", ") ; ", "} }", @@ -191,18 +203,17 @@ fn test_get_expanded_callsite_regular_path() { #[test] fn test_key_to_quoted_no_labels() { - let stream = key_to_quoted(parse_quote! {"mykeyname"}, None); - let expected = "metrics :: KeyData :: from_name (\"mykeyname\")"; + let stream = key_to_quoted(None); + let expected = "metrics :: KeyData :: from_static_name (& METRIC_NAME)"; assert_eq!(stream.to_string(), expected); } #[test] fn test_key_to_quoted_existing_labels() { - let stream = key_to_quoted( - parse_quote! {"mykeyname"}, - Some(Labels::Existing(Expr::Path(parse_quote! { mylabels }))), - ); - let expected = "metrics :: KeyData :: from_parts (\"mykeyname\" , mylabels)"; + let stream = key_to_quoted(Some(Labels::Existing(Expr::Path( + parse_quote! { mylabels }, + )))); + let expected = "metrics :: KeyData :: from_hybrid_parts (& METRIC_NAME , mylabels)"; assert_eq!(stream.to_string(), expected); } @@ -210,15 +221,12 @@ fn test_key_to_quoted_existing_labels() { /// Key). #[test] fn test_key_to_quoted_inline_labels() { - let stream = key_to_quoted( - parse_quote! {"mykeyname"}, - Some(Labels::Inline(vec![ - (parse_quote! {"mylabel1"}, parse_quote! { mylabel1 }), - (parse_quote! {"mylabel2"}, parse_quote! { "mylabel2" }), - ])), - ); + let stream = key_to_quoted(Some(Labels::Inline(vec![ + (parse_quote! {"mylabel1"}, parse_quote! { mylabel1 }), + (parse_quote! {"mylabel2"}, parse_quote! { "mylabel2" }), + ]))); let expected = concat!( - "metrics :: KeyData :: from_parts (\"mykeyname\" , vec ! [", + "metrics :: KeyData :: from_hybrid_parts (& METRIC_NAME , vec ! [", "metrics :: Label :: new (\"mylabel1\" , mylabel1) , ", "metrics :: Label :: new (\"mylabel2\" , \"mylabel2\")", "])" @@ -228,10 +236,7 @@ fn test_key_to_quoted_inline_labels() { #[test] fn test_key_to_quoted_inline_labels_empty() { - let stream = key_to_quoted(parse_quote! {"mykeyname"}, Some(Labels::Inline(vec![]))); - let expected = concat!( - "metrics :: KeyData :: from_parts (\"mykeyname\" , vec ! [", - "])" - ); + let stream = key_to_quoted(Some(Labels::Inline(vec![]))); + let expected = concat!("metrics :: KeyData :: from_hybrid_parts (& METRIC_NAME , vec ! [])"); assert_eq!(stream.to_string(), expected); } diff --git a/metrics-tracing-context/benches/layer.rs b/metrics-tracing-context/benches/layer.rs index 92f1904..ffbb468 100644 --- a/metrics-tracing-context/benches/layer.rs +++ b/metrics-tracing-context/benches/layer.rs @@ -1,5 +1,5 @@ use criterion::{criterion_group, criterion_main, Benchmark, Criterion}; -use metrics::{Key, KeyData, Label, NoopRecorder, Recorder}; +use metrics::{Key, KeyData, Label, NoopRecorder, Recorder, SharedString}; use metrics_tracing_context::{MetricsLayer, TracingContextLayer}; use metrics_util::layers::Layer; use tracing::{ @@ -22,8 +22,9 @@ fn layer_benchmark(c: &mut Criterion) { let tracing_layer = TracingContextLayer::all(); let recorder = tracing_layer.layer(NoopRecorder); - static LABELS: [Label; 1] = [Label::from_static_parts("foo", "bar")]; - static KEY_DATA: KeyData = KeyData::from_static_parts("key", &LABELS); + static KEY_NAME: [SharedString; 1] = [SharedString::const_str("key")]; + static KEY_LABELS: [Label; 1] = [Label::from_static_parts("foo", "bar")]; + static KEY_DATA: KeyData = KeyData::from_static_parts(&KEY_NAME, &KEY_LABELS); b.iter(|| { recorder.increment_counter(Key::Borrowed(&KEY_DATA), 1); @@ -32,8 +33,9 @@ fn layer_benchmark(c: &mut Criterion) { }) .with_function("noop recorder overhead (increment_counter)", |b| { let recorder = NoopRecorder; - static LABELS: [Label; 1] = [Label::from_static_parts("foo", "bar")]; - static KEY_DATA: KeyData = KeyData::from_static_parts("key", &LABELS); + static KEY_NAME: [SharedString; 1] = [SharedString::const_str("key")]; + static KEY_LABELS: [Label; 1] = [Label::from_static_parts("foo", "bar")]; + static KEY_DATA: KeyData = KeyData::from_static_parts(&KEY_NAME, &KEY_LABELS); b.iter(|| { recorder.increment_counter(Key::Borrowed(&KEY_DATA), 1); diff --git a/metrics-tracing-context/src/lib.rs b/metrics-tracing-context/src/lib.rs index 0c5cd28..0d06b25 100644 --- a/metrics-tracing-context/src/lib.rs +++ b/metrics-tracing-context/src/lib.rs @@ -101,7 +101,7 @@ where } } -/// [`TracingContext`] is a [`metrics::Recorder`] that injects labels from [`tracing::Span`]s. +/// [`TracingContext`] is a [`metrics::Recorder`] that injects labels from[`tracing::Span`]s. pub struct TracingContext { inner: R, label_filter: F, @@ -126,7 +126,7 @@ where fn enhance_key(&self, key: Key) -> Key { let (name, mut labels) = key.into_owned().into_parts(); self.enhance_labels(&mut labels); - KeyData::from_parts(name, labels).into() + KeyData::from_owned_parts(name, labels).into() } } diff --git a/metrics-tracing-context/tests/integration.rs b/metrics-tracing-context/tests/integration.rs index 84aba8c..b42d4f5 100644 --- a/metrics-tracing-context/tests/integration.rs +++ b/metrics-tracing-context/tests/integration.rs @@ -52,7 +52,7 @@ fn test_basic_functionality() { snapshot, vec![( MetricKind::Counter, - KeyData::from_parts( + KeyData::from_owned_parts( "login_attempts", vec![ Label::new("service", "login_service"), @@ -95,7 +95,7 @@ fn test_macro_forms() { vec![ ( MetricKind::Counter, - KeyData::from_parts( + KeyData::from_owned_parts( "login_attempts_no_labels", vec![ Label::new("user", "ferris"), @@ -109,7 +109,7 @@ fn test_macro_forms() { ), ( MetricKind::Counter, - KeyData::from_parts( + KeyData::from_owned_parts( "login_attempts_static_labels", vec![ Label::new("service", "login_service"), @@ -124,7 +124,7 @@ fn test_macro_forms() { ), ( MetricKind::Counter, - KeyData::from_parts( + KeyData::from_owned_parts( "login_attempts_dynamic_labels", vec![ Label::new("node_name", "localhost"), @@ -139,7 +139,7 @@ fn test_macro_forms() { ), ( MetricKind::Counter, - KeyData::from_parts( + KeyData::from_owned_parts( "login_attempts_static_and_dynamic_labels", vec![ Label::new("service", "login_service"), @@ -224,7 +224,7 @@ fn test_multiple_paths_to_the_same_callsite() { vec![ ( MetricKind::Counter, - KeyData::from_parts( + KeyData::from_owned_parts( "my_counter", vec![ Label::new("shared_field", "path1"), @@ -239,7 +239,7 @@ fn test_multiple_paths_to_the_same_callsite() { ), ( MetricKind::Counter, - KeyData::from_parts( + KeyData::from_owned_parts( "my_counter", vec![ Label::new("shared_field", "path2"), @@ -295,7 +295,7 @@ fn test_nested_spans() { snapshot, vec![( MetricKind::Counter, - KeyData::from_parts( + KeyData::from_owned_parts( "my_counter", vec![ Label::new("shared_field", "inner"), @@ -340,7 +340,7 @@ fn test_label_filtering() { snapshot, vec![( MetricKind::Counter, - KeyData::from_parts( + KeyData::from_owned_parts( "login_attempts", vec![ Label::new("service", "login_service"), diff --git a/metrics-util/benches/prefix.rs b/metrics-util/benches/prefix.rs index d59b5cc..90a819c 100644 --- a/metrics-util/benches/prefix.rs +++ b/metrics-util/benches/prefix.rs @@ -1,5 +1,5 @@ use criterion::{criterion_group, criterion_main, Benchmark, Criterion}; -use metrics::{Key, KeyData, Label, NameParts, NoopRecorder, Recorder}; +use metrics::{Key, KeyData, Label, NoopRecorder, Recorder, SharedString}; use metrics_util::layers::{Layer, PrefixLayer}; fn layer_benchmark(c: &mut Criterion) { @@ -8,9 +8,9 @@ fn layer_benchmark(c: &mut Criterion) { Benchmark::new("basic", |b| { let prefix_layer = PrefixLayer::new("prefix"); let recorder = prefix_layer.layer(NoopRecorder); - static NAME: NameParts = NameParts::from_static_name("key"); - static LABELS: [Label; 1] = [Label::from_static_parts("foo", "bar")]; - static KEY_DATA: KeyData = KeyData::from_static_parts(&NAME, &LABELS); + static KEY_NAME: [SharedString; 1] = [SharedString::const_str("simple_key")]; + static KEY_LABELS: [Label; 1] = [Label::from_static_parts("foo", "bar")]; + static KEY_DATA: KeyData = KeyData::from_static_parts(&KEY_NAME, &KEY_LABELS); b.iter(|| { recorder.increment_counter(Key::Borrowed(&KEY_DATA), 1); @@ -18,9 +18,9 @@ fn layer_benchmark(c: &mut Criterion) { }) .with_function("noop recorder overhead (increment_counter)", |b| { let recorder = NoopRecorder; - static NAME: NameParts = NameParts::from_static_name("key"); - static LABELS: [Label; 1] = [Label::from_static_parts("foo", "bar")]; - static KEY_DATA: KeyData = KeyData::from_static_parts(&NAME, &LABELS); + static KEY_NAME: [SharedString; 1] = [SharedString::const_str("simple_key")]; + static KEY_LABELS: [Label; 1] = [Label::from_static_parts("foo", "bar")]; + static KEY_DATA: KeyData = KeyData::from_static_parts(&KEY_NAME, &KEY_LABELS); b.iter(|| { recorder.increment_counter(Key::Borrowed(&KEY_DATA), 1); diff --git a/metrics-util/benches/registry.rs b/metrics-util/benches/registry.rs index 7ffe950..a9ad36d 100644 --- a/metrics-util/benches/registry.rs +++ b/metrics-util/benches/registry.rs @@ -1,5 +1,5 @@ use criterion::{criterion_group, criterion_main, BatchSize, Benchmark, Criterion}; -use metrics::{Key, KeyData, Label, NameParts}; +use metrics::{Key, KeyData, Label, SharedString}; use metrics_util::Registry; fn registry_benchmark(c: &mut Criterion) { @@ -7,7 +7,7 @@ fn registry_benchmark(c: &mut Criterion) { "registry", Benchmark::new("cached op (basic)", |b| { let registry: Registry = Registry::new(); - static KEY_NAME: NameParts = NameParts::from_static_name("simple_key"); + static KEY_NAME: [SharedString; 1] = [SharedString::const_str("simple_key")]; static KEY_DATA: KeyData = KeyData::from_static_name(&KEY_NAME); b.iter(|| { @@ -17,7 +17,7 @@ fn registry_benchmark(c: &mut Criterion) { }) .with_function("cached op (labels)", |b| { let registry: Registry = Registry::new(); - static KEY_NAME: NameParts = NameParts::from_static_name("simple_key"); + static KEY_NAME: [SharedString; 1] = [SharedString::const_str("simple_key")]; static KEY_LABELS: [Label; 1] = [Label::from_static_parts("type", "http")]; static KEY_DATA: KeyData = KeyData::from_static_parts(&KEY_NAME, &KEY_LABELS); @@ -64,18 +64,18 @@ fn registry_benchmark(c: &mut Criterion) { b.iter(|| { let key = "simple_key"; let labels = vec![Label::new("type", "http")]; - KeyData::from_parts(key, labels) + KeyData::from_owned_parts(key, labels) }) }) .with_function("const key data overhead (basic)", |b| { b.iter(|| { - static KEY_NAME: NameParts = NameParts::from_static_name("simple_key"); + static KEY_NAME: [SharedString; 1] = [SharedString::const_str("simple_key")]; KeyData::from_static_name(&KEY_NAME) }) }) .with_function("const key data overhead (labels)", |b| { b.iter(|| { - static KEY_NAME: NameParts = NameParts::from_static_name("simple_key"); + static KEY_NAME: [SharedString; 1] = [SharedString::const_str("simple_key")]; static LABELS: [Label; 1] = [Label::from_static_parts("type", "http")]; KeyData::from_static_parts(&KEY_NAME, &LABELS) }) @@ -90,16 +90,16 @@ fn registry_benchmark(c: &mut Criterion) { b.iter(|| { let key = "simple_key"; let labels = vec![Label::new("type", "http")]; - Key::Owned(KeyData::from_parts(key, labels)) + Key::Owned(KeyData::from_owned_parts(key, labels)) }) }) .with_function("cached key overhead (basic)", |b| { - static KEY_NAME: NameParts = NameParts::from_static_name("simple_key"); + static KEY_NAME: [SharedString; 1] = [SharedString::const_str("simple_key")]; static KEY_DATA: KeyData = KeyData::from_static_name(&KEY_NAME); b.iter(|| Key::Borrowed(&KEY_DATA)) }) .with_function("cached key overhead (labels)", |b| { - static KEY_NAME: NameParts = NameParts::from_static_name("simple_key"); + static KEY_NAME: [SharedString; 1] = [SharedString::const_str("simple_key")]; static KEY_LABELS: [Label; 1] = [Label::from_static_parts("type", "http")]; static KEY_DATA: KeyData = KeyData::from_static_parts(&KEY_NAME, &KEY_LABELS); b.iter(|| Key::Borrowed(&KEY_DATA)) diff --git a/metrics-util/src/layers/prefix.rs b/metrics-util/src/layers/prefix.rs index 01918ec..54427d6 100644 --- a/metrics-util/src/layers/prefix.rs +++ b/metrics-util/src/layers/prefix.rs @@ -1,19 +1,17 @@ use crate::layers::Layer; -use metrics::{Key, Recorder, Unit}; +use metrics::{Key, Recorder, SharedString, Unit}; /// Applies a prefix to every metric key. /// /// Keys will be prefixed in the format of `.`. pub struct Prefix { - prefix: &'static str, + prefix: SharedString, inner: R, } impl Prefix { fn prefix_key(&self, key: Key) -> Key { - let mut owned = key.into_owned(); - owned.prepend_name(self.prefix); - owned.into() + key.into_owned().prepend_name(self.prefix.clone()).into() } } @@ -66,7 +64,7 @@ impl Layer for PrefixLayer { fn layer(&self, inner: R) -> Self::Output { Prefix { - prefix: self.0, + prefix: self.0.into(), inner, } } diff --git a/metrics/examples/sizes.rs b/metrics/examples/sizes.rs index ba0f45f..0f711fb 100644 --- a/metrics/examples/sizes.rs +++ b/metrics/examples/sizes.rs @@ -1,13 +1,22 @@ //! This example is purely for development. +use metrics::{Key, KeyData, Label, NameParts, SharedString}; use std::borrow::Cow; -use metrics::{Key, KeyData, NameParts, Label, SharedString}; fn main() { println!("KeyData: {} bytes", std::mem::size_of::()); println!("Key: {} bytes", std::mem::size_of::()); println!("NameParts: {} bytes", std::mem::size_of::()); println!("Label: {} bytes", std::mem::size_of::