use std::time::Instant;
use actix_web::{
dev::{ServiceRequest, ServiceResponse},
HttpMessage,
};
use tracing_actix_web::{DefaultRootSpanBuilder, RootSpanBuilder};
const SLOW_REQUEST_MS: u128 = 5 * 1000;
pub struct StelaeRootSpanBuilder;
struct RequestStart(Instant);
impl RootSpanBuilder for StelaeRootSpanBuilder {
fn on_request_start(request: &ServiceRequest) -> tracing::Span {
{
let mut request_extensions = request.extensions_mut();
request_extensions.insert(RequestStart(Instant::now()));
}
tracing_actix_web::root_span!(
request,
duration_ms = tracing::field::Empty,
duration_ns = tracing::field::Empty,
)
}
fn on_request_end<B>(
span: tracing::Span,
outcome: &Result<ServiceResponse<B>, actix_web::Error>,
) {
outcome.as_ref().map_or((), |response| {
if let Some(req_start) = response.request().extensions().get::<RequestStart>() {
let elapsed = req_start.0.elapsed();
let millis = elapsed.as_millis();
span.record("duration_ms", millis);
span.record("duration_ns", elapsed.as_nanos());
if millis > SLOW_REQUEST_MS {
tracing::warn!(duration_ms = millis, "Slow HTTP request");
} else {
tracing::trace!("HTTP Request");
}
}
});
DefaultRootSpanBuilder::on_request_end(span, outcome);
}
}