mirror of
https://github.com/DefectingCat/phthonus
synced 2025-07-15 16:41:32 +00:00
fix(axum): refactor logging middleware
This commit is contained in:
@ -1,6 +1,16 @@
|
|||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use axum::{
|
use axum::{
|
||||||
body::Body, extract::Request, http::HeaderValue, middleware::Next, response::IntoResponse,
|
body::Bytes,
|
||||||
|
extract::Request,
|
||||||
|
http::{HeaderMap, HeaderValue},
|
||||||
|
middleware::Next,
|
||||||
|
response::{IntoResponse, Response},
|
||||||
|
Router,
|
||||||
};
|
};
|
||||||
|
use tower_http::classify::ServerErrorsFailureClass;
|
||||||
|
use tower_http::trace::TraceLayer;
|
||||||
|
use tracing::{error, info, info_span, Span};
|
||||||
|
|
||||||
use crate::error::AppResult;
|
use crate::error::AppResult;
|
||||||
|
|
||||||
@ -11,7 +21,10 @@ use crate::error::AppResult;
|
|||||||
/// obtaining the response. After receiving the response, it appends two headers:
|
/// obtaining the response. After receiving the response, it appends two headers:
|
||||||
/// - "Server": The name of the server extracted from the Cargo package name.
|
/// - "Server": The name of the server extracted from the Cargo package name.
|
||||||
/// - "S-Version": The version of the server extracted from the Cargo package version.
|
/// - "S-Version": The version of the server extracted from the Cargo package version.
|
||||||
pub async fn add_version(req: Request<Body>, next: Next) -> AppResult<impl IntoResponse> {
|
pub async fn add_version(
|
||||||
|
req: Request<axum::body::Body>,
|
||||||
|
next: Next,
|
||||||
|
) -> AppResult<impl IntoResponse> {
|
||||||
let mut res = next.run(req).await;
|
let mut res = next.run(req).await;
|
||||||
let headers = res.headers_mut();
|
let headers = res.headers_mut();
|
||||||
headers.append("Server", HeaderValue::from_static(env!("CARGO_PKG_NAME")));
|
headers.append("Server", HeaderValue::from_static(env!("CARGO_PKG_NAME")));
|
||||||
@ -21,3 +34,36 @@ pub async fn add_version(req: Request<Body>, next: Next) -> AppResult<impl IntoR
|
|||||||
);
|
);
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Middleware for logging each request.
|
||||||
|
///
|
||||||
|
/// This middleware will calculate each request latency
|
||||||
|
/// and add request's information to each info_span.
|
||||||
|
pub fn logging_route(router: Router) -> Router {
|
||||||
|
router.layer(
|
||||||
|
TraceLayer::new_for_http()
|
||||||
|
.make_span_with(|req: &Request<_>| {
|
||||||
|
let unknown = &HeaderValue::from_static("Unknown");
|
||||||
|
let empty = &HeaderValue::from_static("");
|
||||||
|
let headers = req.headers();
|
||||||
|
let ua = headers
|
||||||
|
.get("User-Agent")
|
||||||
|
.unwrap_or(unknown)
|
||||||
|
.to_str()
|
||||||
|
.unwrap_or("Unknown");
|
||||||
|
let host = headers.get("Host").unwrap_or(empty).to_str().unwrap_or("");
|
||||||
|
info_span!("HTTP", method = ?req.method(), host, uri = ?req.uri(), ua)
|
||||||
|
})
|
||||||
|
.on_request(|_req: &Request<_>, _span: &Span| {})
|
||||||
|
.on_response(|res: &Response, latency: Duration, _span: &Span| {
|
||||||
|
info!("{} {}μs", res.status(), latency.as_micros());
|
||||||
|
})
|
||||||
|
.on_body_chunk(|_chunk: &Bytes, _latency: Duration, _span: &Span| {})
|
||||||
|
.on_eos(|_trailers: Option<&HeaderMap>, _stream_duration: Duration, _span: &Span| {})
|
||||||
|
.on_failure(
|
||||||
|
|error: ServerErrorsFailureClass, _latency: Duration, _span: &Span| {
|
||||||
|
error!("{}", error);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -2,9 +2,8 @@ use std::{borrow::Cow, collections::HashMap, time::Duration};
|
|||||||
|
|
||||||
use axum::{
|
use axum::{
|
||||||
async_trait,
|
async_trait,
|
||||||
body::Bytes,
|
extract::{FromRequestParts, Path},
|
||||||
extract::{FromRequestParts, Path, Request},
|
http::{request::Parts, StatusCode, Uri},
|
||||||
http::{request::Parts, HeaderMap, HeaderValue, StatusCode, Uri},
|
|
||||||
middleware,
|
middleware,
|
||||||
response::{IntoResponse, Response},
|
response::{IntoResponse, Response},
|
||||||
routing::get,
|
routing::get,
|
||||||
@ -12,15 +11,12 @@ use axum::{
|
|||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use tower::ServiceBuilder;
|
use tower::ServiceBuilder;
|
||||||
use tower_http::{
|
use tower_http::{compression::CompressionLayer, cors::CorsLayer, timeout::TimeoutLayer};
|
||||||
classify::ServerErrorsFailureClass, compression::CompressionLayer, cors::CorsLayer,
|
use tracing::info;
|
||||||
timeout::TimeoutLayer, trace::TraceLayer,
|
|
||||||
};
|
|
||||||
use tracing::{error, info, info_span, Span};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error::{AppResult, ErrorCode},
|
error::{AppResult, ErrorCode},
|
||||||
middlewares::add_version,
|
middlewares::{add_version, logging_route},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
@ -36,7 +32,7 @@ where
|
|||||||
pub type RouteResult<T> = AppResult<Json<RouteResponse<T>>>;
|
pub type RouteResult<T> = AppResult<Json<RouteResponse<T>>>;
|
||||||
|
|
||||||
pub fn routes() -> Router {
|
pub fn routes() -> Router {
|
||||||
Router::new()
|
let router = Router::new()
|
||||||
.route("/", get(hello).post(hello))
|
.route("/", get(hello).post(hello))
|
||||||
.layer(
|
.layer(
|
||||||
ServiceBuilder::new()
|
ServiceBuilder::new()
|
||||||
@ -45,35 +41,8 @@ pub fn routes() -> Router {
|
|||||||
.layer(TimeoutLayer::new(Duration::from_secs(15)))
|
.layer(TimeoutLayer::new(Duration::from_secs(15)))
|
||||||
.layer(CompressionLayer::new()),
|
.layer(CompressionLayer::new()),
|
||||||
)
|
)
|
||||||
.fallback(fallback)
|
.fallback(fallback);
|
||||||
.layer(
|
logging_route(router)
|
||||||
TraceLayer::new_for_http()
|
|
||||||
.make_span_with(|req: &Request<_>| {
|
|
||||||
let unknown = &HeaderValue::from_static("Unknown");
|
|
||||||
let empty = &HeaderValue::from_static("");
|
|
||||||
let headers = req.headers();
|
|
||||||
let ua = headers
|
|
||||||
.get("User-Agent")
|
|
||||||
.unwrap_or(unknown)
|
|
||||||
.to_str()
|
|
||||||
.unwrap_or("Unknown");
|
|
||||||
let host = headers.get("Host").unwrap_or(empty).to_str().unwrap_or("");
|
|
||||||
info_span!("HTTP", method = ?req.method(), host, uri = ?req.uri(), ua)
|
|
||||||
})
|
|
||||||
.on_request(|_req: &Request<_>, _span: &Span| {})
|
|
||||||
.on_response(|res: &Response, latency: Duration, _span: &Span| {
|
|
||||||
info!("{} {}μs", res.status(), latency.as_micros());
|
|
||||||
})
|
|
||||||
.on_body_chunk(|_chunk: &Bytes, _latency: Duration, _span: &Span| {})
|
|
||||||
.on_eos(
|
|
||||||
|_trailers: Option<&HeaderMap>, _stream_duration: Duration, _span: &Span| {},
|
|
||||||
)
|
|
||||||
.on_failure(
|
|
||||||
|error: ServerErrorsFailureClass, _latency: Duration, _span: &Span| {
|
|
||||||
error!("{}", error);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// hello world
|
/// hello world
|
||||||
|
Reference in New Issue
Block a user