use ruma::time::Instant;
use tracing::{Callsite as _, callsite::DefaultCallsite};
pub struct TracingTimer {
id: String,
callsite: &'static DefaultCallsite,
start: Instant,
level: tracing::Level,
}
#[cfg(not(tarpaulin_include))]
impl std::fmt::Debug for TracingTimer {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TracingTimer").field("id", &self.id).field("start", &self.start).finish()
}
}
impl Drop for TracingTimer {
fn drop(&mut self) {
let elapsed = self.start.elapsed();
let enabled = tracing::level_enabled!(self.level) && {
let interest = self.callsite.interest();
!interest.is_never()
&& tracing::__macro_support::__is_enabled(self.callsite.metadata(), interest)
};
if !enabled {
return;
}
let message = format!("Timer _{}_ finished in {:?}", self.id, elapsed);
let metadata = self.callsite.metadata();
let fields = metadata.fields();
let message_field = fields.field("message").unwrap();
#[allow(trivial_casts)] let values = [(&message_field, Some(&message as &dyn tracing::Value))];
let values = fields.value_set(&values);
tracing::Event::dispatch(metadata, &values);
}
}
impl TracingTimer {
pub fn new(callsite: &'static DefaultCallsite, id: String, level: tracing::Level) -> Self {
Self { id, callsite, start: Instant::now(), level }
}
}
#[macro_export]
macro_rules! timer {
($level:expr, $string:expr $(,)? ) => {{
static __CALLSITE: tracing::callsite::DefaultCallsite = tracing::callsite2! {
name: tracing::__macro_support::concat!(
"event ",
file!(),
":",
line!(),
),
kind: tracing::metadata::Kind::EVENT,
target: module_path!(),
level: $level,
fields: []
};
$crate::tracing_timer::TracingTimer::new(&__CALLSITE, $string.into(), $level)
}};
($string:expr) => {
$crate::timer!(tracing::Level::DEBUG, $string)
};
}
#[cfg(test)]
mod tests {
#[cfg(not(target_family = "wasm"))]
#[matrix_sdk_test_macros::async_test]
async fn test_timer_name() {
use tracing::{Level, span};
tracing::warn!("Starting test…");
mod time123 {
pub async fn run() {
let _timer_guard = timer!(tracing::Level::DEBUG, "test");
tokio::time::sleep(ruma::time::Duration::from_millis(123)).await;
}
}
time123::run().await;
let span = span!(Level::DEBUG, "le 256ms span");
let _guard = span.enter();
let _timer_guard = timer!("in span");
tokio::time::sleep(ruma::time::Duration::from_millis(256)).await;
tracing::warn!("Test about to finish.");
}
}