use crate::core::Handler;
use crate::{
core::{PingoraHttpRequest, PingoraWebHttpResponse},
error::WebError,
middleware::Middleware,
};
use async_trait::async_trait;
use std::sync::Arc;
use tracing::{Instrument, info};
#[derive(Clone)]
pub struct TracingMiddleware;
impl TracingMiddleware {
pub fn new() -> Self {
Self
}
}
impl Default for TracingMiddleware {
fn default() -> Self {
Self::new()
}
}
#[async_trait]
impl Middleware for TracingMiddleware {
async fn handle(
&self,
req: PingoraHttpRequest,
next: Arc<dyn Handler>,
) -> Result<PingoraWebHttpResponse, WebError> {
let request_id = req
.headers()
.get("x-request-id")
.and_then(|v| v.to_str().ok())
.unwrap_or("")
.to_string();
let method = req.method().as_str().to_string();
let path = req.path().to_string();
let span = tracing::info_span!(
"request",
request_id = request_id.as_str(),
method = method.as_str(),
path = path,
status = tracing::field::Empty,
latency_ms = tracing::field::Empty,
);
let span_for_record = span.clone();
async move {
info!("Request started");
let start_time = std::time::Instant::now();
let res = next.handle(req).await?;
let elapsed_ms = start_time.elapsed().as_millis();
span_for_record.record("status", res.status.as_u16());
span_for_record.record("latency_ms", elapsed_ms);
info!("Request completed");
Ok(res)
}
.instrument(span)
.await
}
}