use std::time::Duration;
use tower_http::trace::TraceLayer;
#[derive(Clone, Copy, Debug, Default)]
pub struct SmartSpanMaker;
impl<B> tower_http::trace::MakeSpan<B> for SmartSpanMaker {
fn make_span(&mut self, req: &http::Request<B>) -> tracing::Span {
let path = req.uri().path();
if path.ends_with("/health") || path.ends_with("/metrics") || path == "/health" || path == "/metrics" {
tracing::trace_span!(
"http.request",
method = %req.method(),
uri = %path,
request_id = tracing::field::Empty,
http.status_code = tracing::field::Empty,
)
} else {
tracing::info_span!(
"http.request",
method = %req.method(),
uri = %path,
request_id = tracing::field::Empty,
http.status_code = tracing::field::Empty,
)
}
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct SmartOnResponse;
impl<B> tower_http::trace::OnResponse<B> for SmartOnResponse {
fn on_response(self, response: &http::Response<B>, _latency: Duration, span: &tracing::Span) {
span.record("http.status_code", response.status().as_u16());
}
}
pub fn smart_trace_layer() -> TraceLayer<
tower_http::classify::SharedClassifier<tower_http::classify::ServerErrorsAsFailures>,
SmartSpanMaker,
tower_http::trace::DefaultOnRequest,
SmartOnResponse,
> {
TraceLayer::new_for_http()
.make_span_with(SmartSpanMaker)
.on_response(SmartOnResponse)
}