1#![deny(missing_docs, unused_crate_dependencies)]
4
5use std::time::Instant;
7
8#[macro_export]
10macro_rules! execution_timer {
11 ($meta:expr) => {
12 let _execution_timer = $crate::ExecutionTimer::init(|start| {
13 tracing::trace!("{} takes {} secs", $meta, start.elapsed().as_secs_f64())
14 });
15 };
16}
17
18#[allow(clippy::tabs_in_doc_comments)]
32pub struct ExecutionTimer<T>
33where
34 T: FnOnce(Instant),
35{
36 pub start: Instant,
38 _tracing: Option<T>,
39}
40impl<T> ExecutionTimer<T>
41where
42 T: FnOnce(Instant),
43{
44 pub fn init(tracing: T) -> Self {
46 Self { start: Instant::now(), _tracing: Some(tracing) }
47 }
48}
49impl<T> Drop for ExecutionTimer<T>
50where
51 T: FnOnce(Instant),
52{
53 fn drop(&mut self) {
54 let _ = self._tracing.take().map(|f| f(self.start));
55 }
56}
57
58#[test]
59#[tracing_test::traced_test]
60fn execution_timer_should_work() {
61 {
62 execution_timer!("test");
63 }
64
65 logs_assert(|log: &[&str]| {
66 let log = &log[0];
67
68 assert!(log.contains("test takes"));
69 assert!(log.contains("secs"));
70
71 Ok(())
72 });
73}