//! Smart tracing span maker for HTTP requests
//!
//! Provides [`SmartSpanMaker`] that automatically downgrades noisy
//! infrastructure endpoints (`/health`, `/metrics`) to `TRACE` level,
//! keeping regular API traffic at `INFO` level.
//!
//! # Example
//!
//! ```ignore
//! use at_jet::middleware::smart_trace_layer;
//!
//! let app = Router::new()
//!     .route("/api/users", get(handler))
//!     .layer(smart_trace_layer());
//! ```

use tower_http::trace::TraceLayer;

/// A span maker that assigns log levels based on the request path.
///
/// - Paths ending with `/health` or `/metrics` → `TRACE` level (quiet)
/// - All other paths → `INFO` level (visible in normal logging)
///
/// This prevents health checks and metrics scrapes from flooding logs
/// while keeping business-relevant traffic visible.
#[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,
      )
    } else {
      tracing::info_span!(
        "http.request",
        method = %req.method(),
        uri = %path,
        request_id = tracing::field::Empty,
      )
    }
  }
}

/// Create a [`TraceLayer`] with [`SmartSpanMaker`] pre-configured.
///
/// This is the recommended way to add HTTP tracing to your server.
/// Health check and metrics endpoints will be logged at `TRACE` level,
/// while all other requests use `INFO` level.
///
/// # Example
///
/// ```ignore
/// use at_jet::middleware::smart_trace_layer;
///
/// let app = Router::new()
///     .route("/api/users", get(handler))
///     .layer(smart_trace_layer());
/// ```
pub fn smart_trace_layer(
) -> TraceLayer<tower_http::classify::SharedClassifier<tower_http::classify::ServerErrorsAsFailures>, SmartSpanMaker>
{
  TraceLayer::new_for_http().make_span_with(SmartSpanMaker)
}
