#[macro_export]
macro_rules! call_hook_traced {
(
$tracer:expr,
$plugin:expr,
$hook:expr,
$method:ident
$(, $arg:expr)*
$(,)?
) => {{
let start = std::time::Instant::now();
let plugin_name = $plugin.to_string();
let method_name = stringify!($method).to_string();
if let Some(ref tracer) = $tracer {
if let Ok(mut t) = tracer.lock() {
t.record_simple(
$crate::trace::TraceEntryType::HookCalled {
hook_name: method_name.clone(),
plugin: plugin_name.clone(),
args: format!("{:?}", ($($arg,)*)),
},
plugin_name.clone(),
);
}
}
let result = $hook.$method($($arg),*).await;
if let Some(ref tracer) = $tracer {
if let Ok(mut t) = tracer.lock() {
let hook_result = if result.is_ok() {
$crate::trace::HookResult::Success
} else {
$crate::trace::HookResult::Error(format!("{:?}", result))
};
t.record_simple(
$crate::trace::TraceEntryType::HookCompleted {
hook_name: method_name,
plugin: plugin_name,
duration_ms: start.elapsed().as_secs_f64() * 1000.0,
result: hook_result,
},
"HookTracer",
);
}
}
result
}};
}
#[cfg(test)]
mod tests {
use crate::trace::EventChainTracer;
use async_trait::async_trait;
use std::sync::{Arc, Mutex};
#[async_trait]
trait TestHook: Send + Sync {
async fn test_method(&self, arg: &str) -> Result<(), String>;
}
struct DummyHook;
#[async_trait]
impl TestHook for DummyHook {
async fn test_method(&self, _arg: &str) -> Result<(), String> {
Ok(())
}
}
#[tokio::test]
async fn test_call_hook_traced_macro() {
let mut tracer = EventChainTracer::new();
tracer.enable();
let tracer = Arc::new(Mutex::new(tracer));
let hook = DummyHook;
let result = call_hook_traced!(
Some(tracer.clone()),
"TestPlugin",
hook,
test_method,
"test_arg"
);
assert!(result.is_ok());
let t = tracer.lock().unwrap();
let traces = t.traces();
assert_eq!(traces.len(), 2);
match &traces[0].entry_type {
crate::trace::TraceEntryType::HookCalled { hook_name, .. } => {
assert_eq!(hook_name, "test_method");
}
_ => panic!("Expected HookCalled"),
}
match &traces[1].entry_type {
crate::trace::TraceEntryType::HookCompleted { hook_name, .. } => {
assert_eq!(hook_name, "test_method");
}
_ => panic!("Expected HookCompleted"),
}
}
}