1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
//! This crate allow to put a `time` attribut macro on any function.
//! It will time the execution of the function and emit a histogram
//! metric using [metrics](https://crates.io/crates/metrics) crate.
//!
//! # Example
//!
//! ```rust
//! use std::error::Error;
//! use metrics_exporter_prometheus::PrometheusBuilder;
//! use function_timer::time;
//!
//! struct Test {}
//!
//! impl Test {
//! #[time("my_metric")]
//! pub fn impl_function(&self) {
//! println!("This another test");
//! }
//!
//! #[time("another_metric")]
//! pub fn impl_fail_function(&self, text:&str) -> Result<(), Box<dyn Error>>{
//! let number:usize = text.parse()?;
//! println!("{number}");
//!
//! Ok(())
//! }
//!
//! #[time("my_metric")]
//! pub fn static_function() {
//! println!("This another test");
//! }
//! }
//!
//! #[time("my_metric")]
//! pub fn free_function() {
//! println!("This a test");
//! }
//!
//! fn main() -> Result<(), Box<dyn Error>> {
//! let builder = PrometheusBuilder::new();
//! let handle = builder.install_recorder()?;
//!
//! free_function();
//!
//! Test::static_function();
//!
//! let t = Test {};
//! t.impl_function();
//!
//! let result = t.impl_fail_function("azerty");
//! assert!(result.is_err());
//! let result = t.impl_fail_function("1");
//! assert!(result.is_ok());
//!
//!
//! println!("{}", handle.render());
//!
//! Ok(())
//! }
//! ```
//!
//! # Note
//!
//! If time is put on functions that have the same names, the only way to distinguish between them
//! is to not use the same metric name. Plan is to allow custom tag on annotation and/or allow to
//! put `time` on an `impl` block.
pub use function_timer_macro::time;
use metrics::histogram;
use std::time::Instant;
/// Timer.
pub struct FunctionTimer {
metric_name: String,
function: String,
chrono: Instant,
}
impl FunctionTimer {
/// Create a new [FunctionTimer].
///
/// # Parameters
///
/// * `metric_name` : name of the metric.
/// * `function` : name of the function that have the annotation. It is used to generate
/// the tag `function`.
pub fn new(metric_name: String, function: String) -> Self {
Self {
metric_name,
function,
chrono: Instant::now(),
}
}
}
impl Drop for FunctionTimer {
/// Get execution time and call [`histogram!`](histogram).
fn drop(&mut self) {
let d = self.chrono.elapsed();
histogram!(self.metric_name.clone(), d, "function" => self.function.clone());
}
}