diff --git a/src/console/ci/e2e/logs_parser.rs b/src/console/ci/e2e/logs_parser.rs index 82e37f7d..ca4d6099 100644 --- a/src/console/ci/e2e/logs_parser.rs +++ b/src/console/ci/e2e/logs_parser.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; const UDP_TRACKER_PATTERN: &str = "[UDP Tracker][INFO] Starting on: udp://"; -const HTTP_TRACKER_PATTERN: &str = "[HTTP Tracker][INFO] Starting on: "; +const HTTP_TRACKER_PATTERN: &str = "[HTTP TRACKER][INFO] Starting on: "; const HEALTH_CHECK_PATTERN: &str = "[HEALTH CHECK API][INFO] Starting on: "; #[derive(Serialize, Deserialize, Debug, Default)] @@ -22,8 +22,8 @@ impl RunningServices { /// 2024-01-24T16:36:14.614898789+00:00 [torrust_tracker::bootstrap::logging][INFO] logging initialized. /// 2024-01-24T16:36:14.615586025+00:00 [UDP Tracker][INFO] Starting on: udp://0.0.0.0:6969 /// 2024-01-24T16:36:14.615623705+00:00 [torrust_tracker::bootstrap::jobs][INFO] TLS not enabled - /// 2024-01-24T16:36:14.615694484+00:00 [HTTP Tracker][INFO] Starting on: http://0.0.0.0:7070 - /// 2024-01-24T16:36:14.615710534+00:00 [HTTP Tracker][INFO] Started on: http://0.0.0.0:7070 + /// 2024-01-24T16:36:14.615694484+00:00 [HTTP TRACKER][INFO] Starting on: http://0.0.0.0:7070 + /// 2024-01-24T16:36:14.615710534+00:00 [HTTP TRACKER][INFO] Started on: http://0.0.0.0:7070 /// 2024-01-24T16:36:14.615716574+00:00 [torrust_tracker::bootstrap::jobs][INFO] TLS not enabled /// 2024-01-24T16:36:14.615764904+00:00 [API][INFO] Starting on http://127.0.0.1:1212 /// 2024-01-24T16:36:14.615767264+00:00 [API][INFO] Started on http://127.0.0.1:1212 @@ -87,7 +87,7 @@ mod tests { fn it_should_parse_from_logs_with_valid_logs() { let logs = "\ [UDP Tracker][INFO] Starting on: udp://0.0.0.0:8080\n\ - [HTTP Tracker][INFO] Starting on: 0.0.0.0:9090\n\ + [HTTP TRACKER][INFO] Starting on: 0.0.0.0:9090\n\ [HEALTH CHECK API][INFO] Starting on: 0.0.0.0:10010"; let running_services = RunningServices::parse_from_logs(logs); diff --git a/src/servers/http/server.rs b/src/servers/http/server.rs index 20e57db5..decc734c 100644 --- a/src/servers/http/server.rs +++ b/src/servers/http/server.rs @@ -40,7 +40,6 @@ pub struct Launcher { impl Launcher { fn start(&self, tracker: Arc, tx_start: Sender, rx_halt: Receiver) -> BoxFuture<'static, ()> { - let app = router(tracker); let socket = std::net::TcpListener::bind(self.bind_to).expect("Could not bind tcp_listener to address."); let address = socket.local_addr().expect("Could not get local_addr from tcp_listener."); @@ -55,7 +54,9 @@ impl Launcher { let tls = self.tls.clone(); let protocol = if tls.is_some() { "https" } else { "http" }; - info!(target: "HTTP Tracker", "Starting on: {protocol}://{}", address); + info!(target: "HTTP TRACKER", "Starting on: {protocol}://{}", address); + + let app = router(tracker, address); let running = Box::pin(async { match tls { @@ -72,7 +73,7 @@ impl Launcher { } }); - info!(target: "HTTP Tracker", "Started on: {protocol}://{}", address); + info!(target: "HTTP TRACKER", "Started on: {protocol}://{}", address); tx_start .send(Started { address }) diff --git a/src/servers/http/v1/routes.rs b/src/servers/http/v1/routes.rs index 20e96d7f..b972cf62 100644 --- a/src/servers/http/v1/routes.rs +++ b/src/servers/http/v1/routes.rs @@ -1,10 +1,20 @@ //! HTTP server routes for version `v1`. +use std::net::SocketAddr; use std::sync::Arc; +use std::time::Duration; +use axum::http::{HeaderName, HeaderValue}; +use axum::response::Response; use axum::routing::get; use axum::Router; use axum_client_ip::SecureClientIpSource; +use hyper::Request; use tower_http::compression::CompressionLayer; +use tower_http::propagate_header::PropagateHeaderLayer; +use tower_http::request_id::{MakeRequestId, RequestId, SetRequestIdLayer}; +use tower_http::trace::{DefaultMakeSpan, TraceLayer}; +use tracing::{Level, Span}; +use uuid::Uuid; use super::handlers::{announce, health_check, scrape}; use crate::core::Tracker; @@ -14,7 +24,7 @@ use crate::core::Tracker; /// > **NOTICE**: it's added a layer to get the client IP from the connection /// info. The tracker could use the connection info to get the client IP. #[allow(clippy::needless_pass_by_value)] -pub fn router(tracker: Arc) -> Router { +pub fn router(tracker: Arc, server_socket_addr: SocketAddr) -> Router { Router::new() // Health check .route("/health_check", get(health_check::handler)) @@ -27,4 +37,47 @@ pub fn router(tracker: Arc) -> Router { // Add extension to get the client IP from the connection info .layer(SecureClientIpSource::ConnectInfo.into_extension()) .layer(CompressionLayer::new()) + .layer(SetRequestIdLayer::x_request_id(RequestIdGenerator)) + .layer(PropagateHeaderLayer::new(HeaderName::from_static("x-request-id"))) + .layer( + TraceLayer::new_for_http() + .make_span_with(DefaultMakeSpan::new().level(Level::INFO)) + .on_request(move |request: &Request, _span: &Span| { + let method = request.method().to_string(); + let uri = request.uri().to_string(); + let request_id = request + .headers() + .get("x-request-id") + .map(|v| v.to_str().unwrap_or_default()) + .unwrap_or_default(); + + tracing::span!( + target:"HTTP TRACKER", + tracing::Level::INFO, "request", server_socket_addr= %server_socket_addr, method = %method, uri = %uri, request_id = %request_id); + }) + .on_response(move |response: &Response, latency: Duration, _span: &Span| { + let status_code = response.status(); + let request_id = response + .headers() + .get("x-request-id") + .map(|v| v.to_str().unwrap_or_default()) + .unwrap_or_default(); + let latency_ms = latency.as_millis(); + + tracing::span!( + target: "HTTP TRACKER", + tracing::Level::INFO, "response", server_socket_addr= %server_socket_addr, latency = %latency_ms, status = %status_code, request_id = %request_id); + }), + ) + .layer(SetRequestIdLayer::x_request_id(RequestIdGenerator)) +} + +#[derive(Clone, Default)] +struct RequestIdGenerator; + +impl MakeRequestId for RequestIdGenerator { + fn make_request_id(&mut self, _request: &Request) -> Option { + let id = HeaderValue::from_str(&Uuid::new_v4().to_string()).expect("UUID is a valid HTTP header value"); + Some(RequestId::new(id)) + } }