metrics_exporter_log/lib.rs
1//! Exports metrics via the `log` crate.
2//!
3//! This exporter can utilize observers that are able to be converted to a textual representation
4//! via [`Drain<String>`]. It will emit that output by logging via the `log` crate at the specified
5//! level.
6//!
7//! # Run Modes
8//! - Using `run` will block the current thread, capturing a snapshot and logging it based on the
9//! configured interval.
10//! - Using `async_run` will return a future that can be awaited on, mimicing the behavior of
11//! `run`.
12#![deny(missing_docs)]
13#[macro_use]
14extern crate log;
15
16use log::Level;
17use metrics_core::{Builder, Drain, Observe, Observer};
18use std::{thread, time::Duration};
19use tokio::time;
20
21/// Exports metrics by converting them to a textual representation and logging them.
22pub struct LogExporter<C, B>
23where
24 B: Builder,
25{
26 controller: C,
27 observer: B::Output,
28 level: Level,
29 interval: Duration,
30}
31
32impl<C, B> LogExporter<C, B>
33where
34 B: Builder,
35 B::Output: Drain<String> + Observer,
36 C: Observe,
37{
38 /// Creates a new [`LogExporter`] that logs at the configurable level.
39 ///
40 /// Observers expose their output by being converted into strings.
41 pub fn new(controller: C, builder: B, level: Level, interval: Duration) -> Self {
42 LogExporter {
43 controller,
44 observer: builder.build(),
45 level,
46 interval,
47 }
48 }
49
50 /// Runs this exporter on the current thread, logging output at the interval
51 /// given on construction.
52 pub fn run(&mut self) {
53 loop {
54 thread::sleep(self.interval);
55
56 self.turn();
57 }
58 }
59
60 /// Run this exporter, logging output only once.
61 pub fn turn(&mut self) {
62 self.controller.observe(&mut self.observer);
63 let output = self.observer.drain();
64 log!(self.level, "{}", output);
65 }
66
67 /// Converts this exporter into a future which logs output at the interval
68 /// given on construction.
69 pub async fn async_run(mut self) {
70 let mut interval = time::interval(self.interval);
71 loop {
72 interval.tick().await;
73 self.turn();
74 }
75 }
76}