Radish alpha
r
rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5
Radicle web interface
Radicle
Git
radicle-explorer radicle-httpd src tracing_extra.rs
use std::fmt;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;

use axum::body::Body;
use axum::extract::ConnectInfo;
use axum::http::Request;
use axum::middleware::Next;
use axum::response::IntoResponse;
use axum::Extension;
use axum_listener::DualAddr;
use hyper::{Method, StatusCode, Uri, Version};

pub use radicle_term::ansi::Paint;

#[derive(Clone)]
pub struct RequestId(Arc<AtomicU64>);

impl RequestId {
    pub fn new() -> RequestId {
        RequestId(Arc::new(0.into()))
    }

    pub fn next(&mut self) -> u64 {
        self.0.fetch_add(1, Ordering::SeqCst)
    }
}

#[derive(Clone)]
pub struct TracingInfo {
    pub connect_info: ConnectInfo<DualAddr>,
    pub method: Method,
    pub version: Version,
    pub uri: Uri,
}

pub struct ColoredStatus(pub StatusCode);

impl fmt::Display for ColoredStatus {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self.0.as_u16() {
            200..=299 => write!(f, "{}", Paint::green(self.0)),
            300..=399 => write!(f, "{}", Paint::blue(self.0)),
            400..=499 => write!(f, "{}", Paint::red(self.0)),
            _ => write!(f, "{}", Paint::yellow(self.0)),
        }
    }
}

pub async fn tracing_middleware(request: Request<Body>, next: Next) -> impl IntoResponse {
    let connect_info = request
        .extensions()
        .get::<ConnectInfo<DualAddr>>()
        .unwrap()
        .clone();

    let method = request.method().clone();
    let version = request.version();
    let uri = request.uri().clone();

    let tracing_info = TracingInfo {
        connect_info,
        method,
        version,
        uri,
    };

    let response = next.run(request).await;

    (Extension(tracing_info), response)
}