#![cfg(feature = "tracing")]
use std::sync::Arc;
use std::time::{Duration, Instant};
use parking_lot::Mutex;
#[derive(Clone, Debug)]
pub struct Trace {
pub created_at: Instant,
pub assemble: Duration,
pub enqueue: Duration,
pub dequeue: Duration,
pub dispatched: Duration,
pub before_serving: Duration,
pub before_server_scheduling: Duration,
pub after_server_scheduling: Duration,
pub before_handling: Duration,
pub after_handling: Duration,
pub server_response: Duration,
pub after_server_response: Duration,
pub after_serving: Duration,
pub served: Duration,
pub response: Duration,
}
#[macro_export]
macro_rules! mark {
($trace:expr, $name:ident) => {{
let mut trace = $trace.inner.lock();
trace.$name = std::time::Instant::now() - trace.created_at;
}};
}
impl Trace {
pub(crate) fn start() -> Trace {
Self {
created_at: Instant::now(),
assemble: Default::default(),
enqueue: Default::default(),
dequeue: Default::default(),
dispatched: Default::default(),
before_serving: Default::default(),
before_server_scheduling: Default::default(),
after_server_scheduling: Default::default(),
before_handling: Default::default(),
after_handling: Default::default(),
server_response: Default::default(),
after_server_response: Default::default(),
after_serving: Default::default(),
served: Default::default(),
response: Default::default(),
}
}
}
#[derive(Clone)]
pub struct TraceHolder {
pub(crate) inner: Arc<Mutex<Trace>>,
}
impl TraceHolder {
pub(crate) fn make() -> Self {
let inner = Trace::start();
Self {
inner: Arc::new(Mutex::new(inner)),
}
}
pub(crate) fn extract(&self) -> Trace {
let mut trace = self.inner.lock().clone();
if trace.served.as_nanos() == 0 {
trace.served = trace.response
}
trace
}
}