Skip to main content

metrics/
macros.rs

1#[doc(hidden)]
2#[macro_export]
3macro_rules! metadata_var {
4    ($target:expr, $level:expr) => {{
5        static METADATA: $crate::Metadata<'static> = $crate::Metadata::new(
6            $target,
7            $level,
8            ::core::option::Option::Some(::core::module_path!()),
9        );
10        &METADATA
11    }};
12}
13
14#[doc(hidden)]
15#[macro_export]
16macro_rules! count {
17    () => {
18        0usize
19    };
20    ($head:tt $($tail:tt)*) => {
21        1usize + $crate::count!($($tail)*)
22    };
23}
24
25#[doc(hidden)]
26#[macro_export]
27macro_rules! key_var {
28    ($name: literal) => {{
29        static METRIC_KEY: $crate::Key = $crate::Key::from_static_name($name);
30        &METRIC_KEY
31    }};
32    ($name:expr) => {
33        $crate::Key::from_name($name)
34    };
35    ($name:literal, $($label_key:literal => $label_value:literal),*) => {{
36        static LABELS: [$crate::Label; $crate::count!($($label_key)*)] = [
37            $($crate::Label::from_static_parts($label_key, $label_value)),*
38        ];
39        static METRIC_KEY: $crate::Key = $crate::Key::from_static_parts($name, &LABELS);
40        &METRIC_KEY
41    }};
42    ($name:expr, $($label_key:literal => $label_value:literal),*) => {{
43        static LABELS: [$crate::Label; $crate::count!($($label_key)*)] = [
44            $($crate::Label::from_static_parts($label_key, $label_value)),*
45        ];
46        $crate::Key::from_static_labels($name, &LABELS)
47    }};
48    ($name:expr, $($label_key:expr => $label_value:expr),*) => {{
49        let labels = ::std::vec![
50            $($crate::Label::new($label_key, $label_value)),*
51        ];
52        $crate::Key::from_parts($name, labels)
53    }};
54    ($name:expr, $labels:expr) => {
55        $crate::Key::from_parts($name, $labels)
56    }
57}
58
59#[doc(hidden)]
60#[macro_export]
61///Internal macro to register metric description when provided by metric creation macro
62macro_rules! __describe_metric {
63    // Do nothing if metric description is not set
64    ($method:ident, __internal_metric_description_none__, __internal_metric_unit_none__, $($rest:tt)*) => {{}};
65    // Show compilation error if `unit` only specified
66    ($method:ident, __internal_metric_description_none__, $unit:expr, $($rest:tt)*) => {{
67        compile_error!("'unit:' requires to specify parameter 'description:'");
68    }};
69    // Found description only
70    ($method:ident, $description:expr, __internal_metric_unit_none__, $name:expr) => {{
71        $crate::with_recorder(|recorder| {
72            recorder.$method(
73                ::core::convert::Into::into($name),
74                ::core::option::Option::None,
75                ::core::convert::Into::into($description),
76            );
77        });
78    }};
79    // Found description + unit
80    ($method:ident, $description:expr, $unit:expr, $name:expr) => {{
81        $crate::with_recorder(|recorder| {
82            recorder.$method(
83                ::core::convert::Into::into($name),
84                ::core::option::Option::Some($unit),
85                ::core::convert::Into::into($description),
86            );
87        });
88    }};
89}
90
91#[doc(hidden)]
92#[macro_export]
93macro_rules! __register_metric {
94    // `target:` — replace the accumulator's `target` slot.
95    (
96        $describe:ident,
97        $register:ident,
98        description = $description:tt,
99        unit = $unit:tt,
100        target = $_old:expr,
101        level = $level:expr;
102        target: $target:expr,
103        $($rest:tt)*
104    ) => {
105        $crate::__register_metric!(
106            $describe,
107            $register,
108            description = $description,
109            unit = $unit,
110            target = $target,
111            level = $level;
112            $($rest)*
113        )
114    };
115    // `level:` — replace the accumulator's `level` slot.
116    (
117        $describe:ident,
118        $register:ident,
119        description = $description:tt,
120        unit = $unit:tt,
121        target = $target:expr,
122        level = $_old:expr;
123        level: $level:expr,
124        $($rest:tt)*
125    ) => {
126        $crate::__register_metric!(
127            $describe,
128            $register,
129            description = $description,
130            unit = $unit,
131            target = $target,
132            level = $level;
133            $($rest)*
134        )
135    };
136    // `description:` — replace the accumulator's `description` slot.
137    (
138        $describe:ident,
139        $register:ident,
140        description = $old:tt,
141        unit = $unit:tt,
142        target = $target:expr,
143        level = $level:expr;
144        description: $description:expr,
145        $($rest:tt)*
146    ) => {
147        $crate::__register_metric!(
148            $describe,
149            $register,
150            description = $description,
151            unit = $unit,
152            target = $target,
153            level = $level;
154            $($rest)*
155        )
156    };
157    // `unit:` — replace the accumulator's `unit` slot.
158    (
159        $describe:ident,
160        $register:ident,
161        description = $description:tt,
162        unit = $old:tt,
163        target = $target:expr,
164        level = $level:expr;
165        unit: $unit:expr,
166        $($rest:tt)*
167    ) => {
168        $crate::__register_metric!(
169            $describe,
170            $register,
171            description = $description,
172            unit = $unit,
173            target = $target,
174            level = $level;
175            $($rest)*
176        )
177    };
178    // Terminator — emit the registration call.
179    (
180        $describe:ident,
181        $register:ident,
182        description = $description:tt,
183        unit = $unit:tt,
184        target = $target:expr,
185        level = $level:expr;
186        $name:expr $(, $label_key:expr $(=> $label_value:expr)?)* $(,)?
187    ) => {{
188        $crate::__describe_metric!($describe, $description, $unit, $name);
189
190        let metric_key = $crate::key_var!($name $(, $label_key $(=> $label_value)?)*);
191        let metadata = $crate::metadata_var!($target, $level);
192
193        $crate::with_recorder(|recorder| recorder.$register(&metric_key, metadata))
194    }};
195}
196
197/// Registers a counter.
198///
199/// Counters represent a single monotonic value, which means the value can only be incremented, not decremented, and
200/// always starts out with an initial value of zero.
201///
202/// A handle to the counter -- [`Counter`](crate::Counter) -- is returned by this macro and can be held on to in order
203/// to amortize the cost of registration.
204///
205/// # Usage
206///
207/// `counter!([named_param: value,] <$name,> [$labels,])`
208///
209/// Only a name is required to initialize a counter.
210///
211/// Named parameters must always come before the counter name, and the counter name must come before any labels.
212///
213/// ## Required parameters
214///
215/// - `$name` - Name of the counter. Must be a string literal or an expression that results in `String` or `&'static str`.
216///
217/// ## Named Parameters
218///
219/// The following parameters can be provided in any order relative to other named parameters:
220///
221/// - `target:` - Module path of the counter. Defaults to `::core::module_path!()`.
222/// - `level:` - Verbosity level of the counter. Defaults to `INFO`.
223/// - `description:` - Description of the counter. If specified, `$name` will be used twice.
224/// - `unit:` - Unit of measurement of the counter. Description must be provided in order to specify units.
225///
226/// ## Labels
227///
228/// Labels can be passed as _one_ of following:
229///
230/// - Arbitrary number of `<key> => <value>` where `key` and `value` can be a string literal or an expression that results in `String` or `&'static str`.
231/// - Static reference to collection of **Label**.
232/// - Collection/iterator that implements [IntoLabels](trait.IntoLabels.html).
233///
234/// # Example
235/// ```
236/// # #![no_implicit_prelude]
237/// # use ::std::convert::From;
238/// # use ::std::format;
239/// # use ::std::string::String;
240/// # use metrics::counter;
241/// # fn main() {
242/// // A basic counter:
243/// let counter = counter!("some_metric_name");
244/// counter.increment(1);
245///
246/// // Specifying labels inline, including using constants for either the key or value:
247/// let counter = counter!("some_metric_name", "service" => "http");
248/// counter.absolute(42);
249///
250/// const SERVICE_LABEL: &'static str = "service";
251/// const SERVICE_HTTP: &'static str = "http";
252/// let counter = counter!("some_metric_name", SERVICE_LABEL => SERVICE_HTTP);
253/// counter.increment(123);
254///
255/// // We can also pass labels by giving a vector or slice of key/value pairs.  In this scenario,
256/// // a unit or description can still be passed in their respective positions:
257/// let dynamic_val = "woo";
258/// let labels = [("dynamic_key", format!("{}!", dynamic_val))];
259/// let counter = counter!("some_metric_name", &labels);
260///
261/// // As mentioned in the documentation, metric names also can be owned strings, including ones
262/// // generated at the callsite via things like `format!`:
263/// let name = String::from("some_owned_metric_name");
264/// let counter = counter!(name);
265///
266/// let counter = counter!(format!("{}_via_format", "name"));
267///
268/// // Using all of the above, we can customize the counter's description, unit, target, and level:
269/// let counter = counter!(
270///     description: "super counter",
271///     unit: metrics::Unit::Bytes,
272///     target: ::core::module_path!(),
273///     level: metrics::Level::INFO,
274///     "super_counter",
275///     "label1" => "value1",
276///     "label2" => "value2"
277/// );
278/// # }
279/// ```
280#[macro_export]
281macro_rules! counter {
282    ($($input:tt)*) => {
283        $crate::__register_metric!(
284            describe_counter,
285            register_counter,
286            description = __internal_metric_description_none__,
287            unit = __internal_metric_unit_none__,
288            target = ::core::module_path!(),
289            level = $crate::Level::INFO;
290            $($input)*
291        )
292    };
293}
294
295/// Registers a gauge.
296///
297/// Gauges represent a single value that can go up or down over time, and always starts out with an initial value of
298/// zero.
299///
300/// A handle to the gauge -- [`Gauge`](crate::Gauge) -- is returned by this macro and can be held on to in order to
301/// amortize the cost of registration.
302///
303/// # Usage
304///
305/// `gauge!([named_param: value,] <$name,> [$labels,])`
306///
307/// Only a name is required to initialize a gauge.
308///
309/// Named parameters must always come before the gauge name, and the gauge name must come before any labels.
310///
311/// ## Required parameters
312///
313/// - `$name` - Name of the gauge. Must be a string literal or an expression that results in `String` or `&'static str`.
314///
315/// ## Named Parameters
316///
317/// The following parameters can be provided in any order relative to other named parameters:
318///
319/// - `target:` - Module path of the gauge. Defaults to `::core::module_path!()`.
320/// - `level:` - Verbosity level of the gauge. Defaults to `INFO`.
321/// - `description:` - Description of the gauge. If specified, `$name` will be used twice.
322/// - `unit:` - Unit of measurement of the gauge. Description must be provided in order to specify units.
323///
324/// ## Labels
325///
326/// Labels can be passed as _one_ of following:
327///
328/// - Arbitrary number of `<key> => <value>` where `key` and `value` can be a string literal or an expression that results in `String` or `&'static str`.
329/// - Static reference to collection of **Label**.
330/// - Collection/iterator that implements [IntoLabels](trait.IntoLabels.html).
331///
332/// # Example
333/// ```
334/// # #![no_implicit_prelude]
335/// # use ::std::string::String;
336/// # use ::std::format;
337/// # use ::std::convert::From;
338/// # use metrics::gauge;
339/// # fn main() {
340/// // A basic gauge:
341/// let gauge = gauge!("some_metric_name");
342/// gauge.increment(1.0);
343///
344/// // Specifying labels inline, including using constants for either the key or value:
345/// let gauge = gauge!("some_metric_name", "service" => "http");
346/// gauge.decrement(42.0);
347///
348/// const SERVICE_LABEL: &'static str = "service";
349/// const SERVICE_HTTP: &'static str = "http";
350/// let gauge = gauge!("some_metric_name", SERVICE_LABEL => SERVICE_HTTP);
351/// gauge.increment(3.14);
352///
353/// // We can also pass labels by giving a vector or slice of key/value pairs.  In this scenario,
354/// // a unit or description can still be passed in their respective positions:
355/// let dynamic_val = "woo";
356/// let labels = [("dynamic_key", format!("{}!", dynamic_val))];
357/// let gauge = gauge!("some_metric_name", &labels);
358/// gauge.set(1337.0);
359///
360/// // As mentioned in the documentation, metric names also can be owned strings, including ones
361/// // generated at the callsite via things like `format!`:
362/// let name = String::from("some_owned_metric_name");
363/// let gauge = gauge!(name);
364///
365/// let gauge = gauge!(format!("{}_via_format", "name"));
366///
367/// // Using all of the above, we can customize the gauge's description, unit, target, and level:
368/// let gauge = gauge!(
369///     description: "super gauge",
370///     unit: metrics::Unit::Bytes,
371///     target: ::core::module_path!(),
372///     level: metrics::Level::INFO,
373///     "super_gauge",
374///     "label1" => "value1",
375///     "label2" => "value2"
376/// );
377/// # }
378/// ```
379#[macro_export]
380macro_rules! gauge {
381    ($($input:tt)*) => {
382        $crate::__register_metric!(
383            describe_gauge,
384            register_gauge,
385            description = __internal_metric_description_none__,
386            unit = __internal_metric_unit_none__,
387            target = ::core::module_path!(),
388            level = $crate::Level::INFO;
389            $($input)*
390        )
391    };
392}
393
394/// Registers a histogram.
395///
396/// Histograms measure the distribution of values for a given set of measurements, and start with no initial values.
397///
398/// A handle to the histogram -- [`Histogram`](crate::Histogram) -- is returned by this macro and can be held on to in
399/// order to amortize the cost of registration.
400///
401/// # Usage
402///
403/// `histogram!([named_param: value,] <$name,> [$labels,])`
404///
405/// Only a name is required to initialize a histogram.
406///
407/// Named parameters must always come before the histogram name, and the histogram name must come before any labels.
408///
409/// ## Required parameters
410///
411/// - `$name` - Name of the histogram. Must be a string literal or an expression that results in `String` or `&'static str`.
412///
413/// ## Named Parameters
414///
415/// The following parameters can be provided in any order relative to other named parameters:
416///
417/// - `target:` - Module path of the histogram. Defaults to `::core::module_path!()`.
418/// - `level:` - Verbosity level of the histogram. Defaults to `INFO`.
419/// - `description:` - Description of the histogram. If specified, `$name` will be used twice.
420/// - `unit:` - Unit of measurement of the histogram. Description must be provided in order to specify units.
421///
422/// ## Labels
423///
424/// Labels can be passed as _one_ of following:
425///
426/// - Arbitrary number of `<key> => <value>` where `key` and `value` can be a string literal or an expression that results in `String` or `&'static str`.
427/// - Static reference to collection of **Label**.
428/// - Collection/iterator that implements [IntoLabels](trait.IntoLabels.html).
429///
430/// # Example
431/// ```
432/// # #![no_implicit_prelude]
433/// # use ::std::string::String;
434/// # use ::std::format;
435/// # use ::std::convert::From;
436/// # use metrics::histogram;
437/// # fn main() {
438/// // A basic histogram:
439/// let histogram = histogram!("some_metric_name");
440/// histogram.record(1.0);
441///
442/// // Specifying labels inline, including using constants for either the key or value:
443/// let histogram = histogram!("some_metric_name", "service" => "http");
444///
445/// const SERVICE_LABEL: &'static str = "service";
446/// const SERVICE_HTTP: &'static str = "http";
447/// let histogram = histogram!("some_metric_name", SERVICE_LABEL => SERVICE_HTTP);
448///
449/// // We can also pass labels by giving a vector or slice of key/value pairs.  In this scenario,
450/// // a unit or description can still be passed in their respective positions:
451/// let dynamic_val = "woo";
452/// let labels = [("dynamic_key", format!("{}!", dynamic_val))];
453/// let histogram = histogram!("some_metric_name", &labels);
454///
455/// // As mentioned in the documentation, metric names also can be owned strings, including ones
456/// // generated at the callsite via things like `format!`:
457/// let name = String::from("some_owned_metric_name");
458/// let histogram = histogram!(name);
459///
460/// let histogram = histogram!(format!("{}_via_format", "name"));
461///
462/// // Using all of the above, we can customize the histogram's description, unit, target, and level:
463/// let histogram = histogram!(
464///     description: "super histogram",
465///     unit: metrics::Unit::Bytes,
466///     target: ::core::module_path!(),
467///     level: metrics::Level::INFO,
468///     "super_histogram",
469///     "label1" => "value1",
470///     "label2" => "value2"
471/// );
472/// # }
473/// ```
474#[macro_export]
475macro_rules! histogram {
476    ($($input:tt)*) => {
477        $crate::__register_metric!(
478            describe_histogram,
479            register_histogram,
480            description = __internal_metric_description_none__,
481            unit = __internal_metric_unit_none__,
482            target = ::core::module_path!(),
483            level = $crate::Level::INFO;
484            $($input)*
485        )
486    };
487}
488
489#[doc(hidden)]
490#[macro_export]
491macro_rules! describe {
492    ($method:ident, $name:expr, $unit:expr, $description:expr $(,)?) => {{
493        $crate::with_recorder(|recorder| {
494            recorder.$method(
495                ::core::convert::Into::into($name),
496                ::core::option::Option::Some($unit),
497                ::core::convert::Into::into($description),
498            );
499        });
500    }};
501    ($method:ident, $name:expr, $description:expr $(,)?) => {{
502        $crate::with_recorder(|recorder| {
503            recorder.$method(
504                ::core::convert::Into::into($name),
505                ::core::option::Option::None,
506                ::core::convert::Into::into($description),
507            );
508        });
509    }};
510}
511
512/// Describes a counter.
513///
514/// Counters represent a single monotonic value, which means the value can only be incremented, not decremented, and
515/// always starts out with an initial value of zero.
516///
517/// Counters can be described with a free-form string, and optionally, a unit can be provided to describe the value
518/// and/or rate of the measurements. Whether or not the installed recorder does anything with the description, or
519/// optional unit, is implementation defined.
520///
521/// # Example
522/// ```
523/// # #![no_implicit_prelude]
524/// # use ::std::convert::From;
525/// # use ::std::format;
526/// # use ::std::string::String;
527/// # use metrics::describe_counter;
528/// # use metrics::Unit;
529/// # fn main() {
530/// // A basic counter:
531/// describe_counter!("some_metric_name", "my favorite counter");
532///
533/// // Providing a unit for a counter:
534/// describe_counter!("some_metric_name", Unit::Bytes, "my favorite counter");
535///
536/// // As mentioned in the documentation, metric names also can be owned strings, including ones
537/// // generated at the callsite via things like `format!`:
538/// let name = String::from("some_owned_metric_name");
539/// describe_counter!(name, "my favorite counter");
540///
541/// describe_counter!(format!("{}_via_format", "name"), "my favorite counter");
542/// # }
543/// ```
544#[macro_export]
545macro_rules! describe_counter {
546    ($name:expr, $unit:expr, $description:expr $(,)?) => {
547        $crate::describe!(describe_counter, $name, $unit, $description)
548    };
549    ($name:expr, $description:expr $(,)?) => {
550        $crate::describe!(describe_counter, $name, $description)
551    };
552}
553
554/// Describes a gauge.
555///
556/// Gauges represent a single value that can go up or down over time, and always starts out with an
557/// initial value of zero.
558///
559/// Gauges can be described with a free-form string, and optionally, a unit can be provided to describe the value
560/// and/or rate of the measurements. Whether or not the installed recorder does anything with the description, or
561/// optional unit, is implementation defined.
562///
563/// # Example
564/// ```
565/// # #![no_implicit_prelude]
566/// # use ::std::convert::From;
567/// # use ::std::format;
568/// # use ::std::string::String;
569/// # use metrics::describe_gauge;
570/// # use metrics::Unit;
571/// # fn main() {
572/// // A basic gauge:
573/// describe_gauge!("some_metric_name", "my favorite gauge");
574///
575/// // Providing a unit for a gauge:
576/// describe_gauge!("some_metric_name", Unit::Bytes, "my favorite gauge");
577///
578/// // As mentioned in the documentation, metric names also can be owned strings, including ones
579/// // generated at the callsite via things like `format!`:
580/// let name = String::from("some_owned_metric_name");
581/// describe_gauge!(name, "my favorite gauge");
582///
583/// describe_gauge!(format!("{}_via_format", "name"), "my favorite gauge");
584/// # }
585/// ```
586#[macro_export]
587macro_rules! describe_gauge {
588    ($name:expr, $unit:expr, $description:expr $(,)?) => {
589        $crate::describe!(describe_gauge, $name, $unit, $description)
590    };
591    ($name:expr, $description:expr $(,)?) => {
592        $crate::describe!(describe_gauge, $name, $description)
593    };
594}
595
596/// Describes a histogram.
597///
598/// Histograms measure the distribution of values for a given set of measurements, and start with no
599/// initial values.
600///
601/// Histograms can be described with a free-form string, and optionally, a unit can be provided to describe the value
602/// and/or rate of the measurements. Whether or not the installed recorder does anything with the description, or
603/// optional unit, is implementation defined.
604///
605/// # Example
606/// ```
607/// # #![no_implicit_prelude]
608/// # use ::std::convert::From;
609/// # use ::std::format;
610/// # use ::std::string::String;
611/// # use metrics::describe_histogram;
612/// # use metrics::Unit;
613/// # fn main() {
614/// // A basic histogram:
615/// describe_histogram!("some_metric_name", "my favorite histogram");
616///
617/// // Providing a unit for a histogram:
618/// describe_histogram!("some_metric_name", Unit::Bytes, "my favorite histogram");
619///
620/// // As mentioned in the documentation, metric names also can be owned strings, including ones
621/// // generated at the callsite via things like `format!`:
622/// let name = String::from("some_owned_metric_name");
623/// describe_histogram!(name, "my favorite histogram");
624///
625/// describe_histogram!(format!("{}_via_format", "name"), "my favorite histogram");
626/// # }
627/// ```
628#[macro_export]
629macro_rules! describe_histogram {
630    ($name:expr, $unit:expr, $description:expr $(,)?) => {
631        $crate::describe!(describe_histogram, $name, $unit, $description)
632    };
633    ($name:expr, $description:expr $(,)?) => {
634        $crate::describe!(describe_histogram, $name, $description)
635    };
636}