Skip to content

Commit 32727ca

Browse files
committed
feat: [torrust#696] API, log request and responses
1 parent 945e91f commit 32727ca

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

src/servers/apis/routes.rs

+52
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,20 @@
66
//! All the API routes have the `/api` prefix and the version number as the
77
//! first path segment. For example: `/api/v1/torrents`.
88
use std::sync::Arc;
9+
use std::time::Duration;
910

11+
use axum::http::{HeaderName, HeaderValue};
12+
use axum::response::Response;
1013
use axum::routing::get;
1114
use axum::{middleware, Router};
15+
use hyper::Request;
1216
use torrust_tracker_configuration::AccessTokens;
1317
use tower_http::compression::CompressionLayer;
18+
use tower_http::propagate_header::PropagateHeaderLayer;
19+
use tower_http::request_id::{MakeRequestId, RequestId, SetRequestIdLayer};
20+
use tower_http::trace::{DefaultMakeSpan, TraceLayer};
21+
use tracing::{Level, Span};
22+
use uuid::Uuid;
1423

1524
use super::v1;
1625
use super::v1::context::health_check::handlers::health_check_handler;
@@ -32,4 +41,47 @@ pub fn router(tracker: Arc<Tracker>, access_tokens: Arc<AccessTokens>) -> Router
3241
.layer(middleware::from_fn_with_state(state, v1::middlewares::auth::auth))
3342
.route(&format!("{api_url_prefix}/health_check"), get(health_check_handler))
3443
.layer(CompressionLayer::new())
44+
.layer(SetRequestIdLayer::x_request_id(RequestIdGenerator))
45+
.layer(PropagateHeaderLayer::new(HeaderName::from_static("x-request-id")))
46+
.layer(
47+
TraceLayer::new_for_http()
48+
.make_span_with(DefaultMakeSpan::new().level(Level::INFO))
49+
.on_request(|request: &Request<axum::body::Body>, _span: &Span| {
50+
let method = request.method().to_string();
51+
let uri = request.uri().to_string();
52+
let request_id = request
53+
.headers()
54+
.get("x-request-id")
55+
.map(|v| v.to_str().unwrap_or_default())
56+
.unwrap_or_default();
57+
58+
tracing::span!(
59+
target: "API",
60+
tracing::Level::INFO, "request", method = %method, uri = %uri, request_id = %request_id);
61+
})
62+
.on_response(|response: &Response, latency: Duration, _span: &Span| {
63+
let status_code = response.status();
64+
let request_id = response
65+
.headers()
66+
.get("x-request-id")
67+
.map(|v| v.to_str().unwrap_or_default())
68+
.unwrap_or_default();
69+
let latency_ms = latency.as_millis();
70+
71+
tracing::span!(
72+
target: "API",
73+
tracing::Level::INFO, "response", latency = %latency_ms, status = %status_code, request_id = %request_id);
74+
}),
75+
)
76+
.layer(SetRequestIdLayer::x_request_id(RequestIdGenerator))
77+
}
78+
79+
#[derive(Clone, Default)]
80+
struct RequestIdGenerator;
81+
82+
impl MakeRequestId for RequestIdGenerator {
83+
fn make_request_id<B>(&mut self, _request: &Request<B>) -> Option<RequestId> {
84+
let id = HeaderValue::from_str(&Uuid::new_v4().to_string()).expect("UUID is a valid HTTP header value");
85+
Some(RequestId::new(id))
86+
}
3587
}

0 commit comments

Comments
 (0)