From 3451d052a4336c487b2c78667b703b60f99a0464 Mon Sep 17 00:00:00 2001 From: Hyeonu Park Date: Mon, 13 Sep 2021 17:45:39 +0900 Subject: [PATCH] Allow trailing comma on macros (#390) Signed-off-by: Hyeonu Park --- src/macros.rs | 545 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 494 insertions(+), 51 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 05b2c4a7..7ae36fec 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -36,6 +36,17 @@ macro_rules! labels { }; } +#[test] +fn test_labels_without_trailing_comma() { + let labels = labels! { + "test" => "hello", + "foo" => "bar" + }; + assert_eq!(labels.len(), 2); + assert!(labels.get("test").is_some()); + assert_eq!(*(labels.get("test").unwrap()), "hello"); +} + /// Create an [`Opts`]. /// /// # Examples @@ -66,7 +77,7 @@ macro_rules! labels { /// ``` #[macro_export] macro_rules! opts { - ( $ NAME : expr , $ HELP : expr $ ( , $ CONST_LABELS : expr ) * ) => { + ( $ NAME : expr , $ HELP : expr $ ( , $ CONST_LABELS : expr ) * $ ( , ) ? ) => { { use std::collections::HashMap; @@ -82,6 +93,31 @@ macro_rules! opts { } } +#[test] +fn test_opts_trailing_comma() { + let name = "test_opts"; + let help = "test opts help"; + + let opts = opts!(name, help,); + assert_eq!(opts.name, name); + assert_eq!(opts.help, help); + + let opts = opts!(name, help, labels! {"test" => "hello", "foo" => "bar",},); + assert_eq!(opts.const_labels.len(), 2); + assert!(opts.const_labels.get("foo").is_some()); + assert_eq!(opts.const_labels.get("foo").unwrap(), "bar"); + + let opts = opts!( + name, + help, + labels! {"test" => "hello", "foo" => "bar",}, + labels! {"ans" => "42",}, + ); + assert_eq!(opts.const_labels.len(), 3); + assert!(opts.const_labels.get("ans").is_some()); + assert_eq!(opts.const_labels.get("ans").unwrap(), "42"); +} + /// Create a [`HistogramOpts`]. /// /// # Examples @@ -115,21 +151,50 @@ macro_rules! opts { /// ``` #[macro_export(local_inner_macros)] macro_rules! histogram_opts { - ($NAME:expr, $HELP:expr) => {{ + ($NAME:expr, $HELP:expr $(,)?) => {{ $crate::HistogramOpts::new($NAME, $HELP) }}; - ($NAME:expr, $HELP:expr, $BUCKETS:expr) => {{ + ($NAME:expr, $HELP:expr, $BUCKETS:expr $(,)?) => {{ let hopts = histogram_opts!($NAME, $HELP); hopts.buckets($BUCKETS) }}; - ($NAME:expr, $HELP:expr, $BUCKETS:expr, $CONST_LABELS:expr) => {{ + ($NAME:expr, $HELP:expr, $BUCKETS:expr, $CONST_LABELS:expr $(,)?) => {{ let hopts = histogram_opts!($NAME, $HELP, $BUCKETS); hopts.const_labels($CONST_LABELS) }}; } +#[test] +fn test_histogram_opts_trailing_comma() { + use crate::linear_buckets; + + let name = "test_histogram_opts"; + let help = "test opts help"; + + let opts = histogram_opts!(name, help,); + assert_eq!(opts.common_opts.name, name); + assert_eq!(opts.common_opts.help, help); + + let opts = histogram_opts!(name, help, linear_buckets(1.0, 0.5, 4).unwrap(),); + assert_eq!(opts.common_opts.name, name); + assert_eq!(opts.common_opts.help, help); + assert_eq!(opts.buckets.len(), 4); + + let opts = histogram_opts!( + name, + help, + vec![1.0, 2.0], + labels! {"key".to_string() => "value".to_string(),}, + ); + assert_eq!(opts.common_opts.name, name); + assert_eq!(opts.common_opts.help, help); + assert_eq!(opts.buckets.len(), 2); + assert!(opts.common_opts.const_labels.get("key").is_some()); + assert_eq!(opts.common_opts.const_labels.get("key").unwrap(), "value"); +} + /// Create a [`Counter`] and registers to default registry. /// /// # Examples @@ -152,15 +217,25 @@ macro_rules! register_counter { $crate::register(Box::new(counter.clone())).map(|_| counter) }}; - ($OPTS:expr) => {{ + ($OPTS:expr $(,)?) => {{ register_counter!(@of_type Counter, $OPTS) }}; - ($NAME:expr, $HELP:expr) => {{ + ($NAME:expr, $HELP:expr $(,)?) => {{ register_counter!(opts!($NAME, $HELP)) }}; } +#[test] +fn test_register_counter_trailing_comma() { + let opts = opts!("test_macro_counter_1", "help",); + let res1 = register_counter!(opts,); + assert!(res1.is_ok()); + + let res2 = register_counter!("test_macro_counter_2", "help",); + assert!(res2.is_ok()); +} + /// Create a [`Counter`] and registers to a custom registry. /// /// # Examples @@ -183,31 +258,46 @@ macro_rules! register_counter { /// ``` #[macro_export(local_inner_macros)] macro_rules! register_counter_with_registry { - (@of_type $TYPE: ident, $OPTS:expr, $REGISTRY:expr) => {{ let counter = $crate::$TYPE::with_opts($OPTS).unwrap(); $REGISTRY.register(Box::new(counter.clone())).map(|_| counter) }}; - ($OPTS:expr, $REGISTRY:expr) => {{ + ($OPTS:expr, $REGISTRY:expr $(,)?) => {{ register_counter_with_registry!(@of_type Counter, $OPTS, $REGISTRY) }}; - ($NAME:expr, $HELP:expr, $REGISTRY:expr) => {{ + ($NAME:expr, $HELP:expr, $REGISTRY:expr $(,)?) => {{ register_counter_with_registry!(opts!($NAME, $HELP), $REGISTRY) }}; } +#[test] +fn test_register_counter_with_registry_trailing_comma() { + use crate::Registry; + use std::collections::HashMap; + + let mut labels = HashMap::new(); + labels.insert("mykey".to_string(), "myvalue".to_string()); + let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap(); + let opts = opts!("test_macro_counter_1", "help",); + let res1 = register_counter_with_registry!(opts, custom_registry,); + assert!(res1.is_ok()); + + let res2 = register_counter_with_registry!("test_macro_counter_2", "help", custom_registry,); + assert!(res2.is_ok()); +} + /// Create an [`IntCounter`] and registers to default registry. /// /// View docs of `register_counter` for examples. #[macro_export(local_inner_macros)] macro_rules! register_int_counter { - ($OPTS:expr) => {{ + ($OPTS:expr $(,)?) => {{ register_counter!(@of_type IntCounter, $OPTS) }}; - ($NAME:expr, $HELP:expr) => {{ + ($NAME:expr, $HELP:expr $(,)?) => {{ register_int_counter!(opts!($NAME, $HELP)) }}; } @@ -217,15 +307,55 @@ macro_rules! register_int_counter { /// View docs of `register_counter_with_registry` for examples. #[macro_export(local_inner_macros)] macro_rules! register_int_counter_with_registry { - ($OPTS:expr, $REGISTRY:expr) => {{ + ($OPTS:expr, $REGISTRY:expr $(,)?) => {{ register_counter_with_registry!(@of_type IntCounter, $OPTS, $REGISTRY) }}; - ($NAME:expr, $HELP:expr, $REGISTRY:expr) => {{ + ($NAME:expr, $HELP:expr, $REGISTRY:expr $(,)?) => {{ register_int_counter_with_registry!(opts!($NAME, $HELP), $REGISTRY) }}; } +#[test] +fn test_register_int_counter() { + use crate::Registry; + use std::collections::HashMap; + + let opts = opts!("test_opts_int_counter_1", "help"); + let res = register_int_counter!(opts); + assert!(res.is_ok()); + + let res = register_int_counter!("test_opts_int_counter_2", "help"); + assert!(res.is_ok()); + + let opts = opts!("test_opts_int_counter_3", "help",); + let res = register_int_counter!(opts,); + assert!(res.is_ok()); + + let res = register_int_counter!("test_opts_int_counter_4", "help",); + assert!(res.is_ok()); + + let mut labels = HashMap::new(); + labels.insert("mykey".to_string(), "myvalue".to_string()); + let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap(); + + let opts = opts!("test_opts_int_counter_1", "help"); + let res = register_int_counter_with_registry!(opts, custom_registry); + assert!(res.is_ok()); + + let res = + register_int_counter_with_registry!("test_opts_int_counter_2", "help", custom_registry); + assert!(res.is_ok()); + + let opts = opts!("test_opts_int_counter_3", "help"); + let res = register_int_counter_with_registry!(opts, custom_registry,); + assert!(res.is_ok()); + + let res = + register_int_counter_with_registry!("test_opts_int_counter_4", "help", custom_registry,); + assert!(res.is_ok()); +} + #[macro_export] #[doc(hidden)] macro_rules! __register_counter_vec { @@ -259,15 +389,25 @@ macro_rules! __register_counter_vec { /// ``` #[macro_export(local_inner_macros)] macro_rules! register_counter_vec { - ($OPTS:expr, $LABELS_NAMES:expr) => {{ + ($OPTS:expr, $LABELS_NAMES:expr $(,)?) => {{ __register_counter_vec!(CounterVec, $OPTS, $LABELS_NAMES) }}; - ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr) => {{ + ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr $(,)?) => {{ register_counter_vec!(opts!($NAME, $HELP), $LABELS_NAMES) }}; } +#[test] +fn test_register_counter_vec_trailing_comma() { + let opts = opts!("test_macro_counter_vec_1", "help",); + let counter_vec = register_counter_vec!(opts, &["a", "b"],); + assert!(counter_vec.is_ok()); + + let counter_vec = register_counter_vec!("test_macro_counter_vec_2", "help", &["a", "b"],); + assert!(counter_vec.is_ok()); +} + /// Create a [`CounterVec`] and registers to a custom registry. /// /// # Examples @@ -291,25 +431,47 @@ macro_rules! register_counter_vec { /// ``` #[macro_export(local_inner_macros)] macro_rules! register_counter_vec_with_registry { - ($OPTS:expr, $LABELS_NAMES:expr, $REGISTRY:expr) => {{ + ($OPTS:expr, $LABELS_NAMES:expr, $REGISTRY:expr $(,)?) => {{ __register_counter_vec!(CounterVec, $OPTS, $LABELS_NAMES, $REGISTRY) }}; - ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr, $REGISTRY:expr) => {{ + ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr, $REGISTRY:expr $(,)?) => {{ register_counter_vec_with_registry!(opts!($NAME, $HELP), $LABELS_NAMES, $REGISTRY) }}; } +#[test] +fn test_register_counter_vec_with_registry_trailing_comma() { + use crate::Registry; + use std::collections::HashMap; + + let mut labels = HashMap::new(); + labels.insert("mykey".to_string(), "myvalue".to_string()); + let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap(); + + let opts = opts!("test_macro_counter_vec_1", "help",); + let counter_vec = register_counter_vec_with_registry!(opts, &["a", "b"], custom_registry,); + assert!(counter_vec.is_ok()); + + let counter_vec = register_counter_vec_with_registry!( + "test_macro_counter_vec_2", + "help", + &["a", "b"], + custom_registry, + ); + assert!(counter_vec.is_ok()); +} + /// Create an [`IntCounterVec`] and registers to default registry. /// /// View docs of `register_counter_vec` for examples. #[macro_export(local_inner_macros)] macro_rules! register_int_counter_vec { - ($OPTS:expr, $LABELS_NAMES:expr) => {{ + ($OPTS:expr, $LABELS_NAMES:expr $(,)?) => {{ __register_counter_vec!(IntCounterVec, $OPTS, $LABELS_NAMES) }}; - ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr) => {{ + ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr $(,)?) => {{ register_int_counter_vec!(opts!($NAME, $HELP), $LABELS_NAMES) }}; } @@ -319,15 +481,63 @@ macro_rules! register_int_counter_vec { /// View docs of `register_counter_vec_with_registry` for examples. #[macro_export(local_inner_macros)] macro_rules! register_int_counter_vec_with_registry { - ($OPTS:expr, $LABELS_NAMES:expr, $REGISTRY:expr) => {{ + ($OPTS:expr, $LABELS_NAMES:expr, $REGISTRY:expr $(,)?) => {{ __register_counter_vec!(IntCounterVec, $OPTS, $LABELS_NAMES, $REGISTRY) }}; - ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr, $REGISTRY:expr) => {{ + ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr, $REGISTRY:expr $(,)?) => {{ register_int_counter_vec_with_registry!(opts!($NAME, $HELP), $LABELS_NAMES, $REGISTRY) }}; } +#[test] +fn test_register_int_counter_vec() { + use crate::Registry; + use std::collections::HashMap; + + let opts = opts!("test_opts_int_counter_vec_1", "help"); + let res = register_int_counter_vec!(opts, &["a", "b"]); + assert!(res.is_ok()); + + let res = register_int_counter_vec!("test_opts_int_counter_vec_2", "help", &["a", "b"]); + assert!(res.is_ok()); + + let opts = opts!("test_opts_int_counter_vec_3", "help",); + let res = register_int_counter_vec!(opts, &["a", "b"],); + assert!(res.is_ok()); + + let res = register_int_counter_vec!("test_opts_int_counter_vec_4", "help", &["a", "b"],); + assert!(res.is_ok()); + + let mut labels = HashMap::new(); + labels.insert("mykey".to_string(), "myvalue".to_string()); + let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap(); + + let opts = opts!("test_opts_int_counter_vec_1", "help"); + let res = register_int_counter_vec_with_registry!(opts, &["a", "b"], custom_registry); + assert!(res.is_ok()); + + let res = register_int_counter_vec_with_registry!( + "test_opts_int_counter_vec_2", + "help", + &["a", "b"], + custom_registry + ); + assert!(res.is_ok()); + + let opts = opts!("test_opts_int_counter_vec_3", "help"); + let res = register_int_counter_vec_with_registry!(opts, &["a", "b"], custom_registry,); + assert!(res.is_ok()); + + let res = register_int_counter_vec_with_registry!( + "test_opts_int_counter_vec_4", + "help", + &["a", "b"], + custom_registry, + ); + assert!(res.is_ok()); +} + #[macro_export] #[doc(hidden)] macro_rules! __register_gauge { @@ -359,15 +569,25 @@ macro_rules! __register_gauge { /// ``` #[macro_export(local_inner_macros)] macro_rules! register_gauge { - ($OPTS:expr) => {{ + ($OPTS:expr $(,)?) => {{ __register_gauge!(Gauge, $OPTS) }}; - ($NAME:expr, $HELP:expr) => {{ + ($NAME:expr, $HELP:expr $(,)?) => {{ register_gauge!(opts!($NAME, $HELP)) }}; } +#[test] +fn test_register_gauge_trailing_comma() { + let opts = opts!("test_macro_gauge", "help",); + let res1 = register_gauge!(opts,); + assert!(res1.is_ok()); + + let res2 = register_gauge!("test_macro_gauge_2", "help",); + assert!(res2.is_ok()); +} + /// Create a [`Gauge`] and registers to a custom registry. /// /// # Examples @@ -391,25 +611,42 @@ macro_rules! register_gauge { /// ``` #[macro_export(local_inner_macros)] macro_rules! register_gauge_with_registry { - ($OPTS:expr, $REGISTRY:expr) => {{ + ($OPTS:expr, $REGISTRY:expr $(,)?) => {{ __register_gauge!(Gauge, $OPTS, $REGISTRY) }}; - ($NAME:expr, $HELP:expr, $REGISTRY:expr) => {{ + ($NAME:expr, $HELP:expr, $REGISTRY:expr $(,)?) => {{ register_gauge_with_registry!(opts!($NAME, $HELP), $REGISTRY) }}; } +#[test] +fn test_register_gauge_with_registry_trailing_comma() { + use crate::Registry; + use std::collections::HashMap; + + let mut labels = HashMap::new(); + labels.insert("mykey".to_string(), "myvalue".to_string()); + let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap(); + + let opts = opts!("test_macro_gauge", "help",); + let res1 = register_gauge_with_registry!(opts, custom_registry,); + assert!(res1.is_ok()); + + let res2 = register_gauge_with_registry!("test_macro_gauge_2", "help", custom_registry,); + assert!(res2.is_ok()); +} + /// Create an [`IntGauge`] and registers to default registry. /// /// View docs of `register_gauge` for examples. #[macro_export(local_inner_macros)] macro_rules! register_int_gauge { - ($OPTS:expr) => {{ + ($OPTS:expr $(,)?) => {{ __register_gauge!(IntGauge, $OPTS) }}; - ($NAME:expr, $HELP:expr) => {{ + ($NAME:expr, $HELP:expr $(,)?) => {{ register_int_gauge!(opts!($NAME, $HELP)) }}; } @@ -419,11 +656,11 @@ macro_rules! register_int_gauge { /// View docs of `register_gauge_with_registry` for examples. #[macro_export(local_inner_macros)] macro_rules! register_int_gauge_with_registry { - ($OPTS:expr, $REGISTRY:expr) => {{ + ($OPTS:expr, $REGISTRY:expr $(,)?) => {{ __register_gauge!(IntGauge, $OPTS, $REGISTRY) }}; - ($NAME:expr, $HELP:expr, $REGISTRY:expr) => {{ + ($NAME:expr, $HELP:expr, $REGISTRY:expr $(,)?) => {{ register_int_gauge_with_registry!(opts!($NAME, $HELP), $REGISTRY) }}; } @@ -431,12 +668,12 @@ macro_rules! register_int_gauge_with_registry { #[macro_export] #[doc(hidden)] macro_rules! __register_gauge_vec { - ($TYPE:ident, $OPTS:expr, $LABELS_NAMES:expr) => {{ + ($TYPE:ident, $OPTS:expr, $LABELS_NAMES:expr $(,)?) => {{ let gauge_vec = $crate::$TYPE::new($OPTS, $LABELS_NAMES).unwrap(); $crate::register(Box::new(gauge_vec.clone())).map(|_| gauge_vec) }}; - ($TYPE:ident, $OPTS:expr, $LABELS_NAMES:expr, $REGISTRY:expr) => {{ + ($TYPE:ident, $OPTS:expr, $LABELS_NAMES:expr, $REGISTRY:expr $(,)?) => {{ let gauge_vec = $crate::$TYPE::new($OPTS, $LABELS_NAMES).unwrap(); $REGISTRY .register(Box::new(gauge_vec.clone())) @@ -444,6 +681,44 @@ macro_rules! __register_gauge_vec { }}; } +#[test] +fn test_register_int_gauge() { + use crate::Registry; + use std::collections::HashMap; + + let opts = opts!("test_opts_int_gauge_1", "help"); + let res = register_int_gauge!(opts); + assert!(res.is_ok()); + + let res = register_int_gauge!("test_opts_int_gauge_2", "help"); + assert!(res.is_ok()); + + let opts = opts!("test_opts_int_gauge_3", "help",); + let res = register_int_gauge!(opts,); + assert!(res.is_ok()); + + let res = register_int_gauge!("test_opts_int_gauge_4", "help",); + assert!(res.is_ok()); + + let mut labels = HashMap::new(); + labels.insert("mykey".to_string(), "myvalue".to_string()); + let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap(); + + let opts = opts!("test_opts_int_gauge_1", "help"); + let res = register_int_gauge_with_registry!(opts, custom_registry); + assert!(res.is_ok()); + + let res = register_int_gauge_with_registry!("test_opts_int_gauge_2", "help", custom_registry); + assert!(res.is_ok()); + + let opts = opts!("test_opts_int_gauge_3", "help"); + let res = register_int_gauge_with_registry!(opts, custom_registry,); + assert!(res.is_ok()); + + let res = register_int_gauge_with_registry!("test_opts_int_gauge_4", "help", custom_registry,); + assert!(res.is_ok()); +} + /// Create a [`GaugeVec`] and registers to default registry. /// /// # Examples @@ -461,15 +736,25 @@ macro_rules! __register_gauge_vec { /// ``` #[macro_export(local_inner_macros)] macro_rules! register_gauge_vec { - ($OPTS:expr, $LABELS_NAMES:expr) => {{ + ($OPTS:expr, $LABELS_NAMES:expr $(,)?) => {{ __register_gauge_vec!(GaugeVec, $OPTS, $LABELS_NAMES) }}; - ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr) => {{ + ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr $(,)?) => {{ register_gauge_vec!(opts!($NAME, $HELP), $LABELS_NAMES) }}; } +#[test] +fn test_register_gauge_vec_trailing_comma() { + let opts = opts!("test_macro_gauge_vec_1", "help",); + let gauge_vec = register_gauge_vec!(opts, &["a", "b"],); + assert!(gauge_vec.is_ok()); + + let gauge_vec = register_gauge_vec!("test_macro_gauge_vec_2", "help", &["a", "b"],); + assert!(gauge_vec.is_ok()); +} + /// Create a [`GaugeVec`] and registers to a custom registry. /// /// # Examples @@ -493,25 +778,47 @@ macro_rules! register_gauge_vec { /// ``` #[macro_export(local_inner_macros)] macro_rules! register_gauge_vec_with_registry { - ($OPTS:expr, $LABELS_NAMES:expr, $REGISTRY:expr) => {{ + ($OPTS:expr, $LABELS_NAMES:expr, $REGISTRY:expr $(,)?) => {{ __register_gauge_vec!(GaugeVec, $OPTS, $LABELS_NAMES, $REGISTRY) }}; - ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr, $REGISTRY:expr) => {{ + ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr, $REGISTRY:expr $(,)?) => {{ register_gauge_vec_with_registry!(opts!($NAME, $HELP), $LABELS_NAMES, $REGISTRY) }}; } +#[test] +fn test_register_gauge_vec_with_registry_trailing_comma() { + use crate::Registry; + use std::collections::HashMap; + + let mut labels = HashMap::new(); + labels.insert("mykey".to_string(), "myvalue".to_string()); + let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap(); + + let opts = opts!("test_macro_gauge_vec_1", "help",); + let gauge_vec = register_gauge_vec_with_registry!(opts, &["a", "b"], custom_registry,); + assert!(gauge_vec.is_ok()); + + let gauge_vec = register_gauge_vec_with_registry!( + "test_macro_gauge_vec_2", + "help", + &["a", "b"], + custom_registry, + ); + assert!(gauge_vec.is_ok()); +} + /// Create an [`IntGaugeVec`] and registers to default registry. /// /// View docs of `register_gauge_vec` for examples. #[macro_export(local_inner_macros)] macro_rules! register_int_gauge_vec { - ($OPTS:expr, $LABELS_NAMES:expr) => {{ + ($OPTS:expr, $LABELS_NAMES:expr $(,)?) => {{ __register_gauge_vec!(IntGaugeVec, $OPTS, $LABELS_NAMES) }}; - ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr) => {{ + ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr $(,)?) => {{ register_int_gauge_vec!(opts!($NAME, $HELP), $LABELS_NAMES) }}; } @@ -521,15 +828,63 @@ macro_rules! register_int_gauge_vec { /// View docs of `register_gauge_vec_with_registry` for examples. #[macro_export(local_inner_macros)] macro_rules! register_int_gauge_vec_with_registry { - ($OPTS:expr, $LABELS_NAMES:expr, $REGISTRY:expr) => {{ + ($OPTS:expr, $LABELS_NAMES:expr, $REGISTRY:expr $(,)?) => {{ __register_gauge_vec!(IntGaugeVec, $OPTS, $LABELS_NAMES, $REGISTRY) }}; - ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr, $REGISTRY:expr) => {{ + ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr, $REGISTRY:expr $(,)?) => {{ register_int_gauge_vec_with_registry!(opts!($NAME, $HELP), $LABELS_NAMES, $REGISTRY) }}; } +#[test] +fn test_register_int_gauge_vec() { + use crate::Registry; + use std::collections::HashMap; + + let opts = opts!("test_opts_int_gauge_vec_1", "help"); + let res = register_int_gauge_vec!(opts, &["a", "b"]); + assert!(res.is_ok()); + + let res = register_int_gauge_vec!("test_opts_int_gauge_vec_2", "help", &["a", "b"]); + assert!(res.is_ok()); + + let opts = opts!("test_opts_int_gauge_vec_3", "help",); + let res = register_int_gauge_vec!(opts, &["a", "b"],); + assert!(res.is_ok()); + + let res = register_int_gauge_vec!("test_opts_int_gauge_vec_4", "help", &["a", "b"],); + assert!(res.is_ok()); + + let mut labels = HashMap::new(); + labels.insert("mykey".to_string(), "myvalue".to_string()); + let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap(); + + let opts = opts!("test_opts_int_gauge_vec_1", "help"); + let res = register_int_gauge_vec_with_registry!(opts, &["a", "b"], custom_registry); + assert!(res.is_ok()); + + let res = register_int_gauge_vec_with_registry!( + "test_opts_int_gauge_vec_2", + "help", + &["a", "b"], + custom_registry + ); + assert!(res.is_ok()); + + let opts = opts!("test_opts_int_gauge_vec_3", "help"); + let res = register_int_gauge_vec_with_registry!(opts, &["a", "b"], custom_registry,); + assert!(res.is_ok()); + + let res = register_int_gauge_vec_with_registry!( + "test_opts_int_gauge_vec_4", + "help", + &["a", "b"], + custom_registry, + ); + assert!(res.is_ok()); +} + /// Create a [`Histogram`] and registers to default registry. /// /// # Examples @@ -552,20 +907,33 @@ macro_rules! register_int_gauge_vec_with_registry { /// ``` #[macro_export(local_inner_macros)] macro_rules! register_histogram { - ($NAME:expr, $HELP:expr) => { + ($NAME:expr, $HELP:expr $(,)?) => { register_histogram!(histogram_opts!($NAME, $HELP)) }; - ($NAME:expr, $HELP:expr, $BUCKETS:expr) => { + ($NAME:expr, $HELP:expr, $BUCKETS:expr $(,)?) => { register_histogram!(histogram_opts!($NAME, $HELP, $BUCKETS)) }; - ($HOPTS:expr) => {{ + ($HOPTS:expr $(,)?) => {{ let histogram = $crate::Histogram::with_opts($HOPTS).unwrap(); $crate::register(Box::new(histogram.clone())).map(|_| histogram) }}; } +#[test] +fn test_register_histogram_trailing_comma() { + let opts = histogram_opts!("test_macro_histogram", "help",); + let res1 = register_histogram!(opts,); + assert!(res1.is_ok()); + + let res2 = register_histogram!("test_macro_histogram_2", "help",); + assert!(res2.is_ok()); + + let res3 = register_histogram!("test_macro_histogram_4", "help", vec![1.0, 2.0],); + assert!(res3.is_ok()); +} + /// Create a [`Histogram`] and registers to a custom registry. /// /// # Examples @@ -594,15 +962,15 @@ macro_rules! register_histogram { /// ``` #[macro_export(local_inner_macros)] macro_rules! register_histogram_with_registry { - ($NAME:expr, $HELP:expr, $REGISTRY:expr) => { + ($NAME:expr, $HELP:expr, $REGISTRY:expr $(,)?) => { register_histogram_with_registry!(histogram_opts!($NAME, $HELP), $REGISTRY) }; - ($NAME:expr, $HELP:expr, $BUCKETS:expr, $REGISTRY:expr) => { + ($NAME:expr, $HELP:expr, $BUCKETS:expr, $REGISTRY:expr $(,)?) => { register_histogram_with_registry!(histogram_opts!($NAME, $HELP, $BUCKETS), $REGISTRY) }; - ($HOPTS:expr, $REGISTRY:expr) => {{ + ($HOPTS:expr, $REGISTRY:expr $(,)?) => {{ let histogram = $crate::Histogram::with_opts($HOPTS).unwrap(); $REGISTRY .register(Box::new(histogram.clone())) @@ -610,6 +978,32 @@ macro_rules! register_histogram_with_registry { }}; } +#[test] +fn test_register_histogram_with_registry_trailing_comma() { + use crate::Registry; + use std::collections::HashMap; + + let mut labels = HashMap::new(); + labels.insert("mykey".to_string(), "myvalue".to_string()); + let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap(); + + let opts = histogram_opts!("test_macro_histogram", "help",); + let res1 = register_histogram_with_registry!(opts, custom_registry,); + assert!(res1.is_ok()); + + let res2 = + register_histogram_with_registry!("test_macro_histogram_2", "help", custom_registry,); + assert!(res2.is_ok()); + + let res3 = register_histogram_with_registry!( + "test_macro_histogram_4", + "help", + vec![1.0, 2.0], + custom_registry, + ); + assert!(res3.is_ok()); +} + /// Create a [`HistogramVec`] and registers to default registry. /// /// # Examples @@ -634,20 +1028,38 @@ macro_rules! register_histogram_with_registry { /// ``` #[macro_export(local_inner_macros)] macro_rules! register_histogram_vec { - ($HOPTS:expr, $LABELS_NAMES:expr) => {{ + ($HOPTS:expr, $LABELS_NAMES:expr $(,)?) => {{ let histogram_vec = $crate::HistogramVec::new($HOPTS, $LABELS_NAMES).unwrap(); $crate::register(Box::new(histogram_vec.clone())).map(|_| histogram_vec) }}; - ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr) => {{ + ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr $(,)?) => {{ register_histogram_vec!(histogram_opts!($NAME, $HELP), $LABELS_NAMES) }}; - ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr, $BUCKETS:expr) => {{ + ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr, $BUCKETS:expr $(,)?) => {{ register_histogram_vec!(histogram_opts!($NAME, $HELP, $BUCKETS), $LABELS_NAMES) }}; } +#[test] +fn test_register_histogram_vec_trailing_comma() { + let opts = histogram_opts!("test_macro_histogram_vec_1", "help",); + let histogram_vec = register_histogram_vec!(opts, &["a", "b"],); + assert!(histogram_vec.is_ok()); + + let histogram_vec = register_histogram_vec!("test_macro_histogram_vec_2", "help", &["a", "b"],); + assert!(histogram_vec.is_ok()); + + let histogram_vec = register_histogram_vec!( + "test_macro_histogram_vec_3", + "help", + &["test_label"], + vec![0.0, 1.0, 2.0], + ); + assert!(histogram_vec.is_ok()); +} + /// Create a [`HistogramVec`] and registers to default registry. /// /// # Examples @@ -678,14 +1090,14 @@ macro_rules! register_histogram_vec { /// ``` #[macro_export(local_inner_macros)] macro_rules! register_histogram_vec_with_registry { - ($HOPTS:expr, $LABELS_NAMES:expr, $REGISTRY:expr) => {{ + ($HOPTS:expr, $LABELS_NAMES:expr, $REGISTRY:expr $(,)?) => {{ let histogram_vec = $crate::HistogramVec::new($HOPTS, $LABELS_NAMES).unwrap(); $REGISTRY .register(Box::new(histogram_vec.clone())) .map(|_| histogram_vec) }}; - ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr, $REGISTRY:expr) => {{ + ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr, $REGISTRY:expr $(,)?) => {{ register_histogram_vec_with_registry!( histogram_opts!($NAME, $HELP), $LABELS_NAMES, @@ -693,7 +1105,7 @@ macro_rules! register_histogram_vec_with_registry { ) }}; - ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr, $BUCKETS:expr, $REGISTRY:expr) => {{ + ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr, $BUCKETS:expr, $REGISTRY:expr $(,)?) => {{ register_histogram_vec_with_registry!( histogram_opts!($NAME, $HELP, $BUCKETS), $LABELS_NAMES, @@ -701,3 +1113,34 @@ macro_rules! register_histogram_vec_with_registry { ) }}; } + +#[test] +fn test_register_histogram_vec_with_registry_trailing_comma() { + use crate::Registry; + use std::collections::HashMap; + + let mut labels = HashMap::new(); + labels.insert("mykey".to_string(), "myvalue".to_string()); + let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap(); + + let opts = histogram_opts!("test_macro_histogram_vec_1", "help",); + let histogram_vec = register_histogram_vec_with_registry!(opts, &["a", "b"], custom_registry,); + assert!(histogram_vec.is_ok()); + + let histogram_vec = register_histogram_vec_with_registry!( + "test_macro_histogram_vec_2", + "help", + &["a", "b"], + custom_registry, + ); + assert!(histogram_vec.is_ok()); + + let histogram_vec = register_histogram_vec_with_registry!( + "test_macro_histogram_vec_3", + "help", + &["test_label"], + vec![0.0, 1.0, 2.0], + custom_registry, + ); + assert!(histogram_vec.is_ok()); +}