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}