prometheus/
macros.rs

1// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.
2
3/// Create labels with specified name-value pairs.
4///
5/// # Examples
6///
7/// ```
8/// # use std::collections::HashMap;
9/// # use prometheus::labels;
10/// # fn main() {
11/// let labels = labels!{
12///     "test" => "hello",
13///     "foo" => "bar",
14/// };
15/// assert_eq!(labels.len(), 2);
16/// assert!(labels.get("test").is_some());
17/// assert_eq!(*(labels.get("test").unwrap()), "hello");
18///
19/// let labels: HashMap<&str, &str> = labels!{};
20/// assert!(labels.is_empty());
21/// # }
22/// ```
23#[macro_export]
24macro_rules! labels {
25    ( $( $ KEY : expr => $ VALUE : expr ),* $(,)? ) => {
26        {
27            use std::collections::HashMap;
28
29            let mut lbs = HashMap::new();
30            $(
31                lbs.insert($KEY, $VALUE);
32            )*
33
34            lbs
35        }
36    };
37}
38
39#[test]
40fn test_labels_without_trailing_comma() {
41    let labels = labels! {
42        "test" => "hello",
43        "foo" => "bar"
44    };
45    assert_eq!(labels.len(), 2);
46    assert!(labels.contains_key("test"));
47    assert_eq!(*(labels.get("test").unwrap()), "hello");
48}
49
50/// Create an [`Opts`][crate::Opts].
51///
52/// # Examples
53///
54/// ```
55/// # use prometheus::{labels, opts};
56/// # fn main() {
57/// let name = "test_opts";
58/// let help = "test opts help";
59///
60/// let opts = opts!(name, help);
61/// assert_eq!(opts.name, name);
62/// assert_eq!(opts.help, help);
63///
64/// let opts = opts!(name, help, labels!{"test" => "hello", "foo" => "bar",});
65/// assert_eq!(opts.const_labels.len(), 2);
66/// assert!(opts.const_labels.get("foo").is_some());
67/// assert_eq!(opts.const_labels.get("foo").unwrap(), "bar");
68///
69/// let opts = opts!(name,
70///                  help,
71///                  labels!{"test" => "hello", "foo" => "bar",},
72///                  labels!{"ans" => "42",});
73/// assert_eq!(opts.const_labels.len(), 3);
74/// assert!(opts.const_labels.get("ans").is_some());
75/// assert_eq!(opts.const_labels.get("ans").unwrap(), "42");
76/// # }
77/// ```
78#[macro_export]
79macro_rules! opts {
80    ( $ NAME : expr , $ HELP : expr $ ( , $ CONST_LABELS : expr ) * $ ( , ) ? ) => {
81        {
82            use std::collections::HashMap;
83
84            let opts = $crate::Opts::new($NAME, $HELP);
85            let lbs = HashMap::<String, String>::new();
86            $(
87                #[allow(clippy::redundant_locals)]
88                let mut lbs = lbs;
89                lbs.extend($CONST_LABELS.iter().map(|(k, v)| ((*k).into(), (*v).into())));
90            )*
91
92            opts.const_labels(lbs)
93        }
94    }
95}
96
97#[test]
98fn test_opts_trailing_comma() {
99    let name = "test_opts";
100    let help = "test opts help";
101
102    let opts = opts!(name, help,);
103    assert_eq!(opts.name, name);
104    assert_eq!(opts.help, help);
105
106    let opts = opts!(name, help, labels! {"test" => "hello", "foo" => "bar",},);
107    assert_eq!(opts.const_labels.len(), 2);
108    assert!(opts.const_labels.contains_key("foo"));
109    assert_eq!(opts.const_labels.get("foo").unwrap(), "bar");
110
111    let opts = opts!(
112        name,
113        help,
114        labels! {"test" => "hello", "foo" => "bar",},
115        labels! {"ans" => "42",},
116    );
117    assert_eq!(opts.const_labels.len(), 3);
118    assert!(opts.const_labels.contains_key("ans"));
119    assert_eq!(opts.const_labels.get("ans").unwrap(), "42");
120}
121
122/// Create a [`HistogramOpts`][crate::HistogramOpts].
123///
124/// # Examples
125///
126/// ```
127/// # use prometheus::linear_buckets;
128/// # use prometheus::{histogram_opts, labels};
129/// # fn main() {
130/// let name = "test_histogram_opts";
131/// let help = "test opts help";
132///
133/// let opts = histogram_opts!(name, help);
134/// assert_eq!(opts.common_opts.name, name);
135/// assert_eq!(opts.common_opts.help, help);
136///
137/// let opts = histogram_opts!(name, help, linear_buckets(1.0, 0.5, 4).unwrap());
138/// assert_eq!(opts.common_opts.name, name);
139/// assert_eq!(opts.common_opts.help, help);
140/// assert_eq!(opts.buckets.len(), 4);
141///
142/// let opts = histogram_opts!(name,
143///                            help,
144///                            vec![1.0, 2.0],
145///                            labels!{"key".to_string() => "value".to_string(),});
146/// assert_eq!(opts.common_opts.name, name);
147/// assert_eq!(opts.common_opts.help, help);
148/// assert_eq!(opts.buckets.len(), 2);
149/// assert!(opts.common_opts.const_labels.get("key").is_some());
150/// assert_eq!(opts.common_opts.const_labels.get("key").unwrap(), "value");
151/// # }
152/// ```
153#[macro_export(local_inner_macros)]
154macro_rules! histogram_opts {
155    ($NAME:expr, $HELP:expr $(,)?) => {{
156        $crate::HistogramOpts::new($NAME, $HELP)
157    }};
158
159    ($NAME:expr, $HELP:expr, $BUCKETS:expr $(,)?) => {{
160        let hopts = histogram_opts!($NAME, $HELP);
161        hopts.buckets($BUCKETS)
162    }};
163
164    ($NAME:expr, $HELP:expr, $BUCKETS:expr, $CONST_LABELS:expr $(,)?) => {{
165        let hopts = histogram_opts!($NAME, $HELP, $BUCKETS);
166        hopts.const_labels($CONST_LABELS)
167    }};
168}
169
170#[test]
171fn test_histogram_opts_trailing_comma() {
172    use crate::linear_buckets;
173
174    let name = "test_histogram_opts";
175    let help = "test opts help";
176
177    let opts = histogram_opts!(name, help,);
178    assert_eq!(opts.common_opts.name, name);
179    assert_eq!(opts.common_opts.help, help);
180
181    let opts = histogram_opts!(name, help, linear_buckets(1.0, 0.5, 4).unwrap(),);
182    assert_eq!(opts.common_opts.name, name);
183    assert_eq!(opts.common_opts.help, help);
184    assert_eq!(opts.buckets.len(), 4);
185
186    let opts = histogram_opts!(
187        name,
188        help,
189        vec![1.0, 2.0],
190        labels! {"key".to_string() => "value".to_string(),},
191    );
192    assert_eq!(opts.common_opts.name, name);
193    assert_eq!(opts.common_opts.help, help);
194    assert_eq!(opts.buckets.len(), 2);
195    assert!(opts.common_opts.const_labels.contains_key("key"));
196    assert_eq!(opts.common_opts.const_labels.get("key").unwrap(), "value");
197}
198
199/// Create a [`Counter`][crate::Counter] and registers to default registry.
200///
201/// # Examples
202///
203/// ```
204/// # use prometheus::{opts, register_counter};
205/// # fn main() {
206/// let opts = opts!("test_macro_counter_1", "help");
207/// let res1 = register_counter!(opts);
208/// assert!(res1.is_ok());
209///
210/// let res2 = register_counter!("test_macro_counter_2", "help");
211/// assert!(res2.is_ok());
212/// # }
213/// ```
214#[macro_export(local_inner_macros)]
215macro_rules! register_counter {
216    (@of_type $TYPE:ident, $OPTS:expr) => {{
217        let counter = $crate::$TYPE::with_opts($OPTS).unwrap();
218        $crate::register(Box::new(counter.clone())).map(|()| counter)
219    }};
220
221    ($OPTS:expr $(,)?) => {{
222        register_counter!(@of_type Counter, $OPTS)
223    }};
224
225    ($NAME:expr, $HELP:expr $(,)?) => {{
226        register_counter!(opts!($NAME, $HELP))
227    }};
228}
229
230#[test]
231fn test_register_counter_trailing_comma() {
232    let opts = opts!("test_macro_counter_1", "help",);
233    let res1 = register_counter!(opts,);
234    assert!(res1.is_ok());
235
236    let res2 = register_counter!("test_macro_counter_2", "help",);
237    assert!(res2.is_ok());
238}
239
240/// Create a [`Counter`][crate::Counter] and registers to a custom registry.
241///
242/// # Examples
243///
244/// ```
245/// # use prometheus::{register_counter_with_registry, opts};
246/// # use prometheus::Registry;
247/// # use std::collections::HashMap;
248/// # fn main() {
249/// let mut labels = HashMap::new();
250/// labels.insert("mykey".to_string(), "myvalue".to_string());
251/// let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap();
252/// let opts = opts!("test_macro_counter_1", "help");
253/// let res1 = register_counter_with_registry!(opts, custom_registry);
254/// assert!(res1.is_ok());
255///
256/// let res2 = register_counter_with_registry!("test_macro_counter_2", "help", custom_registry);
257/// assert!(res2.is_ok());
258/// # }
259/// ```
260#[macro_export(local_inner_macros)]
261macro_rules! register_counter_with_registry {
262    (@of_type $TYPE: ident, $OPTS:expr, $REGISTRY:expr) => {{
263        let counter = $crate::$TYPE::with_opts($OPTS).unwrap();
264        $REGISTRY.register(Box::new(counter.clone())).map(|()| counter)
265    }};
266
267    ($OPTS:expr, $REGISTRY:expr $(,)?) => {{
268        register_counter_with_registry!(@of_type Counter, $OPTS, $REGISTRY)
269    }};
270
271    ($NAME:expr, $HELP:expr, $REGISTRY:expr $(,)?) => {{
272        register_counter_with_registry!(opts!($NAME, $HELP), $REGISTRY)
273    }};
274}
275
276#[test]
277fn test_register_counter_with_registry_trailing_comma() {
278    use crate::Registry;
279    use std::collections::HashMap;
280
281    let mut labels = HashMap::new();
282    labels.insert("mykey".to_string(), "myvalue".to_string());
283    let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap();
284    let opts = opts!("test_macro_counter_1", "help",);
285    let res1 = register_counter_with_registry!(opts, custom_registry,);
286    assert!(res1.is_ok());
287
288    let res2 = register_counter_with_registry!("test_macro_counter_2", "help", custom_registry,);
289    assert!(res2.is_ok());
290}
291
292/// Create an [`IntCounter`][crate::IntCounter] and registers to default registry.
293///
294/// View docs of `register_counter` for examples.
295#[macro_export(local_inner_macros)]
296macro_rules! register_int_counter {
297    ($OPTS:expr $(,)?) => {{
298        register_counter!(@of_type IntCounter, $OPTS)
299    }};
300
301    ($NAME:expr, $HELP:expr $(,)?) => {{
302        register_int_counter!(opts!($NAME, $HELP))
303    }};
304}
305
306/// Create an [`IntCounter`][crate::IntCounter] and registers to a custom registry.
307///
308/// View docs of `register_counter_with_registry` for examples.
309#[macro_export(local_inner_macros)]
310macro_rules! register_int_counter_with_registry {
311    ($OPTS:expr, $REGISTRY:expr $(,)?) => {{
312        register_counter_with_registry!(@of_type IntCounter, $OPTS, $REGISTRY)
313    }};
314
315    ($NAME:expr, $HELP:expr, $REGISTRY:expr $(,)?) => {{
316        register_int_counter_with_registry!(opts!($NAME, $HELP), $REGISTRY)
317    }};
318}
319
320#[test]
321fn test_register_int_counter() {
322    use crate::Registry;
323    use std::collections::HashMap;
324
325    let opts = opts!("test_opts_int_counter_1", "help");
326    let res = register_int_counter!(opts);
327    assert!(res.is_ok());
328
329    let res = register_int_counter!("test_opts_int_counter_2", "help");
330    assert!(res.is_ok());
331
332    let opts = opts!("test_opts_int_counter_3", "help",);
333    let res = register_int_counter!(opts,);
334    assert!(res.is_ok());
335
336    let res = register_int_counter!("test_opts_int_counter_4", "help",);
337    assert!(res.is_ok());
338
339    let mut labels = HashMap::new();
340    labels.insert("mykey".to_string(), "myvalue".to_string());
341    let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap();
342
343    let opts = opts!("test_opts_int_counter_1", "help");
344    let res = register_int_counter_with_registry!(opts, custom_registry);
345    assert!(res.is_ok());
346
347    let res =
348        register_int_counter_with_registry!("test_opts_int_counter_2", "help", custom_registry);
349    assert!(res.is_ok());
350
351    let opts = opts!("test_opts_int_counter_3", "help");
352    let res = register_int_counter_with_registry!(opts, custom_registry,);
353    assert!(res.is_ok());
354
355    let res =
356        register_int_counter_with_registry!("test_opts_int_counter_4", "help", custom_registry,);
357    assert!(res.is_ok());
358}
359
360#[macro_export]
361#[doc(hidden)]
362macro_rules! __register_counter_vec {
363    ($TYPE:ident, $OPTS:expr, $LABELS_NAMES:expr) => {{
364        let counter_vec = $crate::$TYPE::new($OPTS, $LABELS_NAMES).unwrap();
365        $crate::register(Box::new(counter_vec.clone())).map(|()| counter_vec)
366    }};
367
368    ($TYPE:ident, $OPTS:expr, $LABELS_NAMES:expr, $REGISTRY:expr) => {{
369        let counter_vec = $crate::$TYPE::new($OPTS, $LABELS_NAMES).unwrap();
370        $REGISTRY
371            .register(Box::new(counter_vec.clone()))
372            .map(|()| counter_vec)
373    }};
374}
375
376/// Create a [`CounterVec`][crate::CounterVec] and registers to default registry.
377///
378/// # Examples
379///
380/// ```
381/// # use prometheus::{opts, register_counter_vec};
382/// # fn main() {
383/// let opts = opts!("test_macro_counter_vec_1", "help");
384/// let counter_vec = register_counter_vec!(opts, &["a", "b"]);
385/// assert!(counter_vec.is_ok());
386///
387/// let counter_vec = register_counter_vec!("test_macro_counter_vec_2", "help", &["a", "b"]);
388/// assert!(counter_vec.is_ok());
389/// # }
390/// ```
391#[macro_export(local_inner_macros)]
392macro_rules! register_counter_vec {
393    ($OPTS:expr, $LABELS_NAMES:expr $(,)?) => {{
394        __register_counter_vec!(CounterVec, $OPTS, $LABELS_NAMES)
395    }};
396
397    ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr $(,)?) => {{
398        register_counter_vec!(opts!($NAME, $HELP), $LABELS_NAMES)
399    }};
400}
401
402#[test]
403fn test_register_counter_vec_trailing_comma() {
404    let opts = opts!("test_macro_counter_vec_1", "help",);
405    let counter_vec = register_counter_vec!(opts, &["a", "b"],);
406    assert!(counter_vec.is_ok());
407
408    let counter_vec = register_counter_vec!("test_macro_counter_vec_2", "help", &["a", "b"],);
409    assert!(counter_vec.is_ok());
410}
411
412/// Create a [`CounterVec`][crate::CounterVec] and registers to a custom registry.
413///
414/// # Examples
415///
416/// ```
417/// # use prometheus::{register_counter_vec_with_registry, opts};
418/// # use prometheus::Registry;
419/// # use std::collections::HashMap;
420/// # fn main() {
421/// let mut labels = HashMap::new();
422/// labels.insert("mykey".to_string(), "myvalue".to_string());
423/// let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap();
424///
425/// let opts = opts!("test_macro_counter_vec_1", "help");
426/// let counter_vec = register_counter_vec_with_registry!(opts, &["a", "b"], custom_registry);
427/// assert!(counter_vec.is_ok());
428///
429/// let counter_vec = register_counter_vec_with_registry!("test_macro_counter_vec_2", "help", &["a", "b"], custom_registry);
430/// assert!(counter_vec.is_ok());
431/// # }
432/// ```
433#[macro_export(local_inner_macros)]
434macro_rules! register_counter_vec_with_registry {
435    ($OPTS:expr, $LABELS_NAMES:expr, $REGISTRY:expr $(,)?) => {{
436        __register_counter_vec!(CounterVec, $OPTS, $LABELS_NAMES, $REGISTRY)
437    }};
438
439    ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr, $REGISTRY:expr $(,)?) => {{
440        register_counter_vec_with_registry!(opts!($NAME, $HELP), $LABELS_NAMES, $REGISTRY)
441    }};
442}
443
444#[test]
445fn test_register_counter_vec_with_registry_trailing_comma() {
446    use crate::Registry;
447    use std::collections::HashMap;
448
449    let mut labels = HashMap::new();
450    labels.insert("mykey".to_string(), "myvalue".to_string());
451    let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap();
452
453    let opts = opts!("test_macro_counter_vec_1", "help",);
454    let counter_vec = register_counter_vec_with_registry!(opts, &["a", "b"], custom_registry,);
455    assert!(counter_vec.is_ok());
456
457    let counter_vec = register_counter_vec_with_registry!(
458        "test_macro_counter_vec_2",
459        "help",
460        &["a", "b"],
461        custom_registry,
462    );
463    assert!(counter_vec.is_ok());
464}
465
466/// Create an [`IntCounterVec`][crate::IntCounterVec] and registers to default registry.
467///
468/// View docs of `register_counter_vec` for examples.
469#[macro_export(local_inner_macros)]
470macro_rules! register_int_counter_vec {
471    ($OPTS:expr, $LABELS_NAMES:expr $(,)?) => {{
472        __register_counter_vec!(IntCounterVec, $OPTS, $LABELS_NAMES)
473    }};
474
475    ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr $(,)?) => {{
476        register_int_counter_vec!(opts!($NAME, $HELP), $LABELS_NAMES)
477    }};
478}
479
480/// Create an [`IntCounterVec`][crate::IntCounterVec] and registers to a custom registry.
481///
482/// View docs of `register_counter_vec_with_registry` for examples.
483#[macro_export(local_inner_macros)]
484macro_rules! register_int_counter_vec_with_registry {
485    ($OPTS:expr, $LABELS_NAMES:expr, $REGISTRY:expr $(,)?) => {{
486        __register_counter_vec!(IntCounterVec, $OPTS, $LABELS_NAMES, $REGISTRY)
487    }};
488
489    ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr, $REGISTRY:expr $(,)?) => {{
490        register_int_counter_vec_with_registry!(opts!($NAME, $HELP), $LABELS_NAMES, $REGISTRY)
491    }};
492}
493
494#[test]
495fn test_register_int_counter_vec() {
496    use crate::Registry;
497    use std::collections::HashMap;
498
499    let opts = opts!("test_opts_int_counter_vec_1", "help");
500    let res = register_int_counter_vec!(opts, &["a", "b"]);
501    assert!(res.is_ok());
502
503    let res = register_int_counter_vec!("test_opts_int_counter_vec_2", "help", &["a", "b"]);
504    assert!(res.is_ok());
505
506    let opts = opts!("test_opts_int_counter_vec_3", "help",);
507    let res = register_int_counter_vec!(opts, &["a", "b"],);
508    assert!(res.is_ok());
509
510    let res = register_int_counter_vec!("test_opts_int_counter_vec_4", "help", &["a", "b"],);
511    assert!(res.is_ok());
512
513    let mut labels = HashMap::new();
514    labels.insert("mykey".to_string(), "myvalue".to_string());
515    let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap();
516
517    let opts = opts!("test_opts_int_counter_vec_1", "help");
518    let res = register_int_counter_vec_with_registry!(opts, &["a", "b"], custom_registry);
519    assert!(res.is_ok());
520
521    let res = register_int_counter_vec_with_registry!(
522        "test_opts_int_counter_vec_2",
523        "help",
524        &["a", "b"],
525        custom_registry
526    );
527    assert!(res.is_ok());
528
529    let opts = opts!("test_opts_int_counter_vec_3", "help");
530    let res = register_int_counter_vec_with_registry!(opts, &["a", "b"], custom_registry,);
531    assert!(res.is_ok());
532
533    let res = register_int_counter_vec_with_registry!(
534        "test_opts_int_counter_vec_4",
535        "help",
536        &["a", "b"],
537        custom_registry,
538    );
539    assert!(res.is_ok());
540}
541
542#[macro_export]
543#[doc(hidden)]
544macro_rules! __register_gauge {
545    ($TYPE:ident, $OPTS:expr) => {{
546        let gauge = $crate::$TYPE::with_opts($OPTS).unwrap();
547        $crate::register(Box::new(gauge.clone())).map(|()| gauge)
548    }};
549
550    ($TYPE:ident, $OPTS:expr, $REGISTRY:expr) => {{
551        let gauge = $crate::$TYPE::with_opts($OPTS).unwrap();
552        $REGISTRY.register(Box::new(gauge.clone())).map(|()| gauge)
553    }};
554}
555
556/// Create a [`Gauge`][crate::Gauge] and registers to default registry.
557///
558/// # Examples
559///
560/// ```
561/// # use prometheus::{opts, register_gauge};
562/// # fn main() {
563/// let opts = opts!("test_macro_gauge", "help");
564/// let res1 = register_gauge!(opts);
565/// assert!(res1.is_ok());
566///
567/// let res2 = register_gauge!("test_macro_gauge_2", "help");
568/// assert!(res2.is_ok());
569/// # }
570/// ```
571#[macro_export(local_inner_macros)]
572macro_rules! register_gauge {
573    ($OPTS:expr $(,)?) => {{
574        __register_gauge!(Gauge, $OPTS)
575    }};
576
577    ($NAME:expr, $HELP:expr $(,)?) => {{
578        register_gauge!(opts!($NAME, $HELP))
579    }};
580}
581
582#[test]
583fn test_register_gauge_trailing_comma() {
584    let opts = opts!("test_macro_gauge", "help",);
585    let res1 = register_gauge!(opts,);
586    assert!(res1.is_ok());
587
588    let res2 = register_gauge!("test_macro_gauge_2", "help",);
589    assert!(res2.is_ok());
590}
591
592/// Create a [`Gauge`][crate::Gauge] and registers to a custom registry.
593///
594/// # Examples
595///
596/// ```
597/// # use prometheus::{register_gauge_with_registry, opts};
598/// # use prometheus::Registry;
599/// # use std::collections::HashMap;
600/// # fn main() {
601/// let mut labels = HashMap::new();
602/// labels.insert("mykey".to_string(), "myvalue".to_string());
603/// let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap();
604///
605/// let opts = opts!("test_macro_gauge", "help");
606/// let res1 = register_gauge_with_registry!(opts, custom_registry);
607/// assert!(res1.is_ok());
608///
609/// let res2 = register_gauge_with_registry!("test_macro_gauge_2", "help", custom_registry);
610/// assert!(res2.is_ok());
611/// # }
612/// ```
613#[macro_export(local_inner_macros)]
614macro_rules! register_gauge_with_registry {
615    ($OPTS:expr, $REGISTRY:expr $(,)?) => {{
616        __register_gauge!(Gauge, $OPTS, $REGISTRY)
617    }};
618
619    ($NAME:expr, $HELP:expr, $REGISTRY:expr $(,)?) => {{
620        register_gauge_with_registry!(opts!($NAME, $HELP), $REGISTRY)
621    }};
622}
623
624#[test]
625fn test_register_gauge_with_registry_trailing_comma() {
626    use crate::Registry;
627    use std::collections::HashMap;
628
629    let mut labels = HashMap::new();
630    labels.insert("mykey".to_string(), "myvalue".to_string());
631    let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap();
632
633    let opts = opts!("test_macro_gauge", "help",);
634    let res1 = register_gauge_with_registry!(opts, custom_registry,);
635    assert!(res1.is_ok());
636
637    let res2 = register_gauge_with_registry!("test_macro_gauge_2", "help", custom_registry,);
638    assert!(res2.is_ok());
639}
640
641/// Create an [`IntGauge`][crate::IntGauge] and registers to default registry.
642///
643/// View docs of `register_gauge` for examples.
644#[macro_export(local_inner_macros)]
645macro_rules! register_int_gauge {
646    ($OPTS:expr $(,)?) => {{
647        __register_gauge!(IntGauge, $OPTS)
648    }};
649
650    ($NAME:expr, $HELP:expr $(,)?) => {{
651        register_int_gauge!(opts!($NAME, $HELP))
652    }};
653}
654
655/// Create an [`IntGauge`][crate::IntGauge] and registers to a custom registry.
656///
657/// View docs of `register_gauge_with_registry` for examples.
658#[macro_export(local_inner_macros)]
659macro_rules! register_int_gauge_with_registry {
660    ($OPTS:expr, $REGISTRY:expr $(,)?) => {{
661        __register_gauge!(IntGauge, $OPTS, $REGISTRY)
662    }};
663
664    ($NAME:expr, $HELP:expr, $REGISTRY:expr $(,)?) => {{
665        register_int_gauge_with_registry!(opts!($NAME, $HELP), $REGISTRY)
666    }};
667}
668
669#[macro_export]
670#[doc(hidden)]
671macro_rules! __register_gauge_vec {
672    ($TYPE:ident, $OPTS:expr, $LABELS_NAMES:expr $(,)?) => {{
673        let gauge_vec = $crate::$TYPE::new($OPTS, $LABELS_NAMES).unwrap();
674        $crate::register(Box::new(gauge_vec.clone())).map(|()| gauge_vec)
675    }};
676
677    ($TYPE:ident, $OPTS:expr, $LABELS_NAMES:expr, $REGISTRY:expr $(,)?) => {{
678        let gauge_vec = $crate::$TYPE::new($OPTS, $LABELS_NAMES).unwrap();
679        $REGISTRY
680            .register(Box::new(gauge_vec.clone()))
681            .map(|()| gauge_vec)
682    }};
683}
684
685#[test]
686fn test_register_int_gauge() {
687    use crate::Registry;
688    use std::collections::HashMap;
689
690    let opts = opts!("test_opts_int_gauge_1", "help");
691    let res = register_int_gauge!(opts);
692    assert!(res.is_ok());
693
694    let res = register_int_gauge!("test_opts_int_gauge_2", "help");
695    assert!(res.is_ok());
696
697    let opts = opts!("test_opts_int_gauge_3", "help",);
698    let res = register_int_gauge!(opts,);
699    assert!(res.is_ok());
700
701    let res = register_int_gauge!("test_opts_int_gauge_4", "help",);
702    assert!(res.is_ok());
703
704    let mut labels = HashMap::new();
705    labels.insert("mykey".to_string(), "myvalue".to_string());
706    let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap();
707
708    let opts = opts!("test_opts_int_gauge_1", "help");
709    let res = register_int_gauge_with_registry!(opts, custom_registry);
710    assert!(res.is_ok());
711
712    let res = register_int_gauge_with_registry!("test_opts_int_gauge_2", "help", custom_registry);
713    assert!(res.is_ok());
714
715    let opts = opts!("test_opts_int_gauge_3", "help");
716    let res = register_int_gauge_with_registry!(opts, custom_registry,);
717    assert!(res.is_ok());
718
719    let res = register_int_gauge_with_registry!("test_opts_int_gauge_4", "help", custom_registry,);
720    assert!(res.is_ok());
721}
722
723/// Create a [`GaugeVec`][crate::GaugeVec] and registers to default registry.
724///
725/// # Examples
726///
727/// ```
728/// # use prometheus::{opts, register_gauge_vec};
729/// # fn main() {
730/// let opts = opts!("test_macro_gauge_vec_1", "help");
731/// let gauge_vec = register_gauge_vec!(opts, &["a", "b"]);
732/// assert!(gauge_vec.is_ok());
733///
734/// let gauge_vec = register_gauge_vec!("test_macro_gauge_vec_2", "help", &["a", "b"]);
735/// assert!(gauge_vec.is_ok());
736/// # }
737/// ```
738#[macro_export(local_inner_macros)]
739macro_rules! register_gauge_vec {
740    ($OPTS:expr, $LABELS_NAMES:expr $(,)?) => {{
741        __register_gauge_vec!(GaugeVec, $OPTS, $LABELS_NAMES)
742    }};
743
744    ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr $(,)?) => {{
745        register_gauge_vec!(opts!($NAME, $HELP), $LABELS_NAMES)
746    }};
747}
748
749#[test]
750fn test_register_gauge_vec_trailing_comma() {
751    let opts = opts!("test_macro_gauge_vec_1", "help",);
752    let gauge_vec = register_gauge_vec!(opts, &["a", "b"],);
753    assert!(gauge_vec.is_ok());
754
755    let gauge_vec = register_gauge_vec!("test_macro_gauge_vec_2", "help", &["a", "b"],);
756    assert!(gauge_vec.is_ok());
757}
758
759/// Create a [`GaugeVec`][crate::GaugeVec] and registers to a custom registry.
760///
761/// # Examples
762///
763/// ```
764/// # use prometheus::{register_gauge_vec_with_registry, opts};
765/// # use prometheus::Registry;
766/// # use std::collections::HashMap;
767/// # fn main() {
768/// let mut labels = HashMap::new();
769/// labels.insert("mykey".to_string(), "myvalue".to_string());
770/// let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap();
771///
772/// let opts = opts!("test_macro_gauge_vec_1", "help");
773/// let gauge_vec = register_gauge_vec_with_registry!(opts, &["a", "b"], custom_registry);
774/// assert!(gauge_vec.is_ok());
775///
776/// let gauge_vec = register_gauge_vec_with_registry!("test_macro_gauge_vec_2", "help", &["a", "b"], custom_registry);
777/// assert!(gauge_vec.is_ok());
778/// # }
779/// ```
780#[macro_export(local_inner_macros)]
781macro_rules! register_gauge_vec_with_registry {
782    ($OPTS:expr, $LABELS_NAMES:expr, $REGISTRY:expr $(,)?) => {{
783        __register_gauge_vec!(GaugeVec, $OPTS, $LABELS_NAMES, $REGISTRY)
784    }};
785
786    ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr, $REGISTRY:expr $(,)?) => {{
787        register_gauge_vec_with_registry!(opts!($NAME, $HELP), $LABELS_NAMES, $REGISTRY)
788    }};
789}
790
791#[test]
792fn test_register_gauge_vec_with_registry_trailing_comma() {
793    use crate::Registry;
794    use std::collections::HashMap;
795
796    let mut labels = HashMap::new();
797    labels.insert("mykey".to_string(), "myvalue".to_string());
798    let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap();
799
800    let opts = opts!("test_macro_gauge_vec_1", "help",);
801    let gauge_vec = register_gauge_vec_with_registry!(opts, &["a", "b"], custom_registry,);
802    assert!(gauge_vec.is_ok());
803
804    let gauge_vec = register_gauge_vec_with_registry!(
805        "test_macro_gauge_vec_2",
806        "help",
807        &["a", "b"],
808        custom_registry,
809    );
810    assert!(gauge_vec.is_ok());
811}
812
813/// Create an [`IntGaugeVec`][crate::IntGaugeVec] and registers to default registry.
814///
815/// View docs of `register_gauge_vec` for examples.
816#[macro_export(local_inner_macros)]
817macro_rules! register_int_gauge_vec {
818    ($OPTS:expr, $LABELS_NAMES:expr $(,)?) => {{
819        __register_gauge_vec!(IntGaugeVec, $OPTS, $LABELS_NAMES)
820    }};
821
822    ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr $(,)?) => {{
823        register_int_gauge_vec!(opts!($NAME, $HELP), $LABELS_NAMES)
824    }};
825}
826
827/// Create an [`IntGaugeVec`][crate::IntGaugeVec] and registers to a custom registry.
828///
829/// View docs of `register_gauge_vec_with_registry` for examples.
830#[macro_export(local_inner_macros)]
831macro_rules! register_int_gauge_vec_with_registry {
832    ($OPTS:expr, $LABELS_NAMES:expr, $REGISTRY:expr $(,)?) => {{
833        __register_gauge_vec!(IntGaugeVec, $OPTS, $LABELS_NAMES, $REGISTRY)
834    }};
835
836    ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr, $REGISTRY:expr $(,)?) => {{
837        register_int_gauge_vec_with_registry!(opts!($NAME, $HELP), $LABELS_NAMES, $REGISTRY)
838    }};
839}
840
841#[test]
842fn test_register_int_gauge_vec() {
843    use crate::Registry;
844    use std::collections::HashMap;
845
846    let opts = opts!("test_opts_int_gauge_vec_1", "help");
847    let res = register_int_gauge_vec!(opts, &["a", "b"]);
848    assert!(res.is_ok());
849
850    let res = register_int_gauge_vec!("test_opts_int_gauge_vec_2", "help", &["a", "b"]);
851    assert!(res.is_ok());
852
853    let opts = opts!("test_opts_int_gauge_vec_3", "help",);
854    let res = register_int_gauge_vec!(opts, &["a", "b"],);
855    assert!(res.is_ok());
856
857    let res = register_int_gauge_vec!("test_opts_int_gauge_vec_4", "help", &["a", "b"],);
858    assert!(res.is_ok());
859
860    let mut labels = HashMap::new();
861    labels.insert("mykey".to_string(), "myvalue".to_string());
862    let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap();
863
864    let opts = opts!("test_opts_int_gauge_vec_1", "help");
865    let res = register_int_gauge_vec_with_registry!(opts, &["a", "b"], custom_registry);
866    assert!(res.is_ok());
867
868    let res = register_int_gauge_vec_with_registry!(
869        "test_opts_int_gauge_vec_2",
870        "help",
871        &["a", "b"],
872        custom_registry
873    );
874    assert!(res.is_ok());
875
876    let opts = opts!("test_opts_int_gauge_vec_3", "help");
877    let res = register_int_gauge_vec_with_registry!(opts, &["a", "b"], custom_registry,);
878    assert!(res.is_ok());
879
880    let res = register_int_gauge_vec_with_registry!(
881        "test_opts_int_gauge_vec_4",
882        "help",
883        &["a", "b"],
884        custom_registry,
885    );
886    assert!(res.is_ok());
887}
888
889/// Create a [`Histogram`][crate::Histogram] and registers to default registry.
890///
891/// # Examples
892///
893/// ```
894/// # use prometheus::{histogram_opts, register_histogram};
895/// # fn main() {
896/// let opts = histogram_opts!("test_macro_histogram", "help");
897/// let res1 = register_histogram!(opts);
898/// assert!(res1.is_ok());
899///
900/// let res2 = register_histogram!("test_macro_histogram_2", "help");
901/// assert!(res2.is_ok());
902///
903/// let res3 = register_histogram!("test_macro_histogram_4",
904///                                 "help",
905///                                 vec![1.0, 2.0]);
906/// assert!(res3.is_ok());
907/// # }
908/// ```
909#[macro_export(local_inner_macros)]
910macro_rules! register_histogram {
911    ($NAME:expr, $HELP:expr $(,)?) => {
912        register_histogram!(histogram_opts!($NAME, $HELP))
913    };
914
915    ($NAME:expr, $HELP:expr, $BUCKETS:expr $(,)?) => {
916        register_histogram!(histogram_opts!($NAME, $HELP, $BUCKETS))
917    };
918
919    ($HOPTS:expr $(,)?) => {{
920        let histogram = $crate::Histogram::with_opts($HOPTS).unwrap();
921        $crate::register(Box::new(histogram.clone())).map(|()| histogram)
922    }};
923}
924
925#[test]
926fn test_register_histogram_trailing_comma() {
927    let opts = histogram_opts!("test_macro_histogram", "help",);
928    let res1 = register_histogram!(opts,);
929    assert!(res1.is_ok());
930
931    let res2 = register_histogram!("test_macro_histogram_2", "help",);
932    assert!(res2.is_ok());
933
934    let res3 = register_histogram!("test_macro_histogram_4", "help", vec![1.0, 2.0],);
935    assert!(res3.is_ok());
936}
937
938/// Create a [`Histogram`][crate::Histogram] and registers to a custom registry.
939///
940/// # Examples
941///
942/// ```
943/// # use prometheus::{register_histogram_with_registry, histogram_opts};
944/// # use prometheus::Registry;
945/// # use std::collections::HashMap;
946/// # fn main() {
947/// let mut labels = HashMap::new();
948/// labels.insert("mykey".to_string(), "myvalue".to_string());
949/// let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap();
950///
951/// let opts = histogram_opts!("test_macro_histogram", "help");
952/// let res1 = register_histogram_with_registry!(opts, custom_registry);
953/// assert!(res1.is_ok());
954///
955/// let res2 = register_histogram_with_registry!("test_macro_histogram_2", "help", custom_registry);
956/// assert!(res2.is_ok());
957///
958/// let res3 = register_histogram_with_registry!("test_macro_histogram_4",
959///                                 "help",
960///                                 vec![1.0, 2.0], custom_registry);
961/// assert!(res3.is_ok());
962/// # }
963/// ```
964#[macro_export(local_inner_macros)]
965macro_rules! register_histogram_with_registry {
966    ($NAME:expr, $HELP:expr, $REGISTRY:expr $(,)?) => {
967        register_histogram_with_registry!(histogram_opts!($NAME, $HELP), $REGISTRY)
968    };
969
970    ($NAME:expr, $HELP:expr, $BUCKETS:expr, $REGISTRY:expr $(,)?) => {
971        register_histogram_with_registry!(histogram_opts!($NAME, $HELP, $BUCKETS), $REGISTRY)
972    };
973
974    ($HOPTS:expr, $REGISTRY:expr $(,)?) => {{
975        let histogram = $crate::Histogram::with_opts($HOPTS).unwrap();
976        $REGISTRY
977            .register(Box::new(histogram.clone()))
978            .map(|()| histogram)
979    }};
980}
981
982#[test]
983fn test_register_histogram_with_registry_trailing_comma() {
984    use crate::Registry;
985    use std::collections::HashMap;
986
987    let mut labels = HashMap::new();
988    labels.insert("mykey".to_string(), "myvalue".to_string());
989    let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap();
990
991    let opts = histogram_opts!("test_macro_histogram", "help",);
992    let res1 = register_histogram_with_registry!(opts, custom_registry,);
993    assert!(res1.is_ok());
994
995    let res2 =
996        register_histogram_with_registry!("test_macro_histogram_2", "help", custom_registry,);
997    assert!(res2.is_ok());
998
999    let res3 = register_histogram_with_registry!(
1000        "test_macro_histogram_4",
1001        "help",
1002        vec![1.0, 2.0],
1003        custom_registry,
1004    );
1005    assert!(res3.is_ok());
1006}
1007
1008/// Create a [`HistogramVec`][crate::HistogramVec] and registers to default registry.
1009///
1010/// # Examples
1011///
1012/// ```
1013/// # use prometheus::{histogram_opts, register_histogram_vec};
1014/// # fn main() {
1015/// let opts = histogram_opts!("test_macro_histogram_vec_1", "help");
1016/// let histogram_vec = register_histogram_vec!(opts, &["a", "b"]);
1017/// assert!(histogram_vec.is_ok());
1018///
1019/// let histogram_vec =
1020///     register_histogram_vec!("test_macro_histogram_vec_2", "help", &["a", "b"]);
1021/// assert!(histogram_vec.is_ok());
1022///
1023/// let histogram_vec = register_histogram_vec!("test_macro_histogram_vec_3",
1024///                                             "help",
1025///                                             &["test_label"],
1026///                                             vec![0.0, 1.0, 2.0]);
1027/// assert!(histogram_vec.is_ok());
1028/// # }
1029/// ```
1030#[macro_export(local_inner_macros)]
1031macro_rules! register_histogram_vec {
1032    ($HOPTS:expr, $LABELS_NAMES:expr $(,)?) => {{
1033        let histogram_vec = $crate::HistogramVec::new($HOPTS, $LABELS_NAMES).unwrap();
1034        $crate::register(Box::new(histogram_vec.clone())).map(|()| histogram_vec)
1035    }};
1036
1037    ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr $(,)?) => {{
1038        register_histogram_vec!(histogram_opts!($NAME, $HELP), $LABELS_NAMES)
1039    }};
1040
1041    ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr, $BUCKETS:expr $(,)?) => {{
1042        register_histogram_vec!(histogram_opts!($NAME, $HELP, $BUCKETS), $LABELS_NAMES)
1043    }};
1044}
1045
1046#[test]
1047fn test_register_histogram_vec_trailing_comma() {
1048    let opts = histogram_opts!("test_macro_histogram_vec_1", "help",);
1049    let histogram_vec = register_histogram_vec!(opts, &["a", "b"],);
1050    assert!(histogram_vec.is_ok());
1051
1052    let histogram_vec = register_histogram_vec!("test_macro_histogram_vec_2", "help", &["a", "b"],);
1053    assert!(histogram_vec.is_ok());
1054
1055    let histogram_vec = register_histogram_vec!(
1056        "test_macro_histogram_vec_3",
1057        "help",
1058        &["test_label"],
1059        vec![0.0, 1.0, 2.0],
1060    );
1061    assert!(histogram_vec.is_ok());
1062}
1063
1064/// Create a [`HistogramVec`][crate::HistogramVec] and registers to a custom registry.
1065///
1066/// # Examples
1067///
1068/// ```
1069/// # use prometheus::{register_histogram_vec_with_registry, histogram_opts};
1070/// # use prometheus::Registry;
1071/// # use std::collections::HashMap;
1072/// # fn main() {
1073/// let mut labels = HashMap::new();
1074/// labels.insert("mykey".to_string(), "myvalue".to_string());
1075/// let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap();
1076///
1077/// let opts = histogram_opts!("test_macro_histogram_vec_1", "help");
1078/// let histogram_vec = register_histogram_vec_with_registry!(opts, &["a", "b"], custom_registry);
1079/// assert!(histogram_vec.is_ok());
1080///
1081/// let histogram_vec =
1082///     register_histogram_vec_with_registry!("test_macro_histogram_vec_2", "help", &["a", "b"], custom_registry);
1083/// assert!(histogram_vec.is_ok());
1084///
1085/// let histogram_vec = register_histogram_vec_with_registry!("test_macro_histogram_vec_3",
1086///                                             "help",
1087///                                             &["test_label"],
1088///                                             vec![0.0, 1.0, 2.0], custom_registry);
1089/// assert!(histogram_vec.is_ok());
1090/// # }
1091/// ```
1092#[macro_export(local_inner_macros)]
1093macro_rules! register_histogram_vec_with_registry {
1094    ($HOPTS:expr, $LABELS_NAMES:expr, $REGISTRY:expr $(,)?) => {{
1095        let histogram_vec = $crate::HistogramVec::new($HOPTS, $LABELS_NAMES).unwrap();
1096        $REGISTRY
1097            .register(Box::new(histogram_vec.clone()))
1098            .map(|()| histogram_vec)
1099    }};
1100
1101    ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr, $REGISTRY:expr $(,)?) => {{
1102        register_histogram_vec_with_registry!(
1103            histogram_opts!($NAME, $HELP),
1104            $LABELS_NAMES,
1105            $REGISTRY
1106        )
1107    }};
1108
1109    ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr, $BUCKETS:expr, $REGISTRY:expr $(,)?) => {{
1110        register_histogram_vec_with_registry!(
1111            histogram_opts!($NAME, $HELP, $BUCKETS),
1112            $LABELS_NAMES,
1113            $REGISTRY
1114        )
1115    }};
1116}
1117
1118#[test]
1119fn test_register_histogram_vec_with_registry_trailing_comma() {
1120    use crate::Registry;
1121    use std::collections::HashMap;
1122
1123    let mut labels = HashMap::new();
1124    labels.insert("mykey".to_string(), "myvalue".to_string());
1125    let custom_registry = Registry::new_custom(Some("myprefix".to_string()), Some(labels)).unwrap();
1126
1127    let opts = histogram_opts!("test_macro_histogram_vec_1", "help",);
1128    let histogram_vec = register_histogram_vec_with_registry!(opts, &["a", "b"], custom_registry,);
1129    assert!(histogram_vec.is_ok());
1130
1131    let histogram_vec = register_histogram_vec_with_registry!(
1132        "test_macro_histogram_vec_2",
1133        "help",
1134        &["a", "b"],
1135        custom_registry,
1136    );
1137    assert!(histogram_vec.is_ok());
1138
1139    let histogram_vec = register_histogram_vec_with_registry!(
1140        "test_macro_histogram_vec_3",
1141        "help",
1142        &["test_label"],
1143        vec![0.0, 1.0, 2.0],
1144        custom_registry,
1145    );
1146    assert!(histogram_vec.is_ok());
1147}