diff --git a/Cargo.lock b/Cargo.lock index 6b04e273b..aae5deb9e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3479,6 +3479,8 @@ dependencies = [ "torrust-tracker-primitives", "torrust-tracker-test-helpers", "tower-http", + "trace", + "tracing", "url", "uuid", ] @@ -3567,6 +3569,8 @@ dependencies = [ "tokio-util", "tower-layer", "tower-service", + "tracing", + "uuid", ] [[package]] @@ -3581,6 +3585,17 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +[[package]] +name = "trace" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ad0c048e114d19d1140662762bfdb10682f3bc806d8be18af846600214dd9af" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "tracing" version = "0.1.40" @@ -3589,9 +3604,21 @@ checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "log", "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "tracing-core" version = "0.1.32" diff --git a/Cargo.toml b/Cargo.toml index bd04e1cc1..83134d8f0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,7 +67,7 @@ torrust-tracker-configuration = { version = "3.0.0-alpha.12-develop", path = "pa torrust-tracker-contrib-bencode = { version = "3.0.0-alpha.12-develop", path = "contrib/bencode" } torrust-tracker-located-error = { version = "3.0.0-alpha.12-develop", path = "packages/located-error" } torrust-tracker-primitives = { version = "3.0.0-alpha.12-develop", path = "packages/primitives" } -tower-http = { version = "0", features = ["compression-full"] } +tower-http = { version = "0", features = ["compression-full", "cors", "trace", "propagate-header", "request-id"] } uuid = { version = "1", features = ["v4"] } colored = "2.1.0" url = "2.5.0" @@ -75,6 +75,8 @@ tempfile = "3.9.0" clap = { version = "4.4.18", features = ["derive", "env"]} anyhow = "1.0.79" hex-literal = "0.4.1" +trace = "0.1.7" +tracing = "0.1.40" [dev-dependencies] criterion = { version = "0.5.1", features = ["async_tokio"] } diff --git a/cSpell.json b/cSpell.json index aaa3229c2..646037e59 100644 --- a/cSpell.json +++ b/cSpell.json @@ -117,6 +117,7 @@ "Swatinem", "Swiftbit", "taiki", + "tdyne", "tempfile", "thiserror", "tlsv", diff --git a/contrib/bencode/src/mutable/encode.rs b/contrib/bencode/src/mutable/encode.rs index 811c35816..25c91b41d 100644 --- a/contrib/bencode/src/mutable/encode.rs +++ b/contrib/bencode/src/mutable/encode.rs @@ -1,5 +1,3 @@ -use std::iter::Extend; - use crate::access::bencode::{BRefAccess, RefKind}; use crate::access::dict::BDictAccess; use crate::access::list::BListAccess; diff --git a/contrib/bencode/src/reference/bencode_ref.rs b/contrib/bencode/src/reference/bencode_ref.rs index 760dd3016..a6f2c15bc 100644 --- a/contrib/bencode/src/reference/bencode_ref.rs +++ b/contrib/bencode/src/reference/bencode_ref.rs @@ -125,8 +125,6 @@ impl<'a> BRefAccessExt<'a> for BencodeRef<'a> { #[cfg(test)] mod tests { - use std::default::Default; - use crate::access::bencode::BRefAccess; use crate::reference::bencode_ref::BencodeRef; use crate::reference::decode_opt::BDecodeOpt; diff --git a/contrib/bencode/src/reference/decode.rs b/contrib/bencode/src/reference/decode.rs index d2aa180f8..d35d1b597 100644 --- a/contrib/bencode/src/reference/decode.rs +++ b/contrib/bencode/src/reference/decode.rs @@ -177,8 +177,6 @@ fn peek_byte(bytes: &[u8], pos: usize) -> BencodeParseResult { #[cfg(test)] mod tests { - use std::default::Default; - use crate::access::bencode::BRefAccess; use crate::reference::bencode_ref::BencodeRef; use crate::reference::decode_opt::BDecodeOpt; diff --git a/contrib/bencode/src/reference/decode_opt.rs b/contrib/bencode/src/reference/decode_opt.rs index e8d9a8337..8409cc72c 100644 --- a/contrib/bencode/src/reference/decode_opt.rs +++ b/contrib/bencode/src/reference/decode_opt.rs @@ -1,5 +1,3 @@ -use std::default::Default; - const DEFAULT_MAX_RECURSION: usize = 50; const DEFAULT_CHECK_KEY_SORT: bool = false; const DEFAULT_ENFORCE_FULL_DECODE: bool = true; diff --git a/src/console/clients/checker/config.rs b/src/console/clients/checker/config.rs index 0a2c09b03..6e44d889b 100644 --- a/src/console/clients/checker/config.rs +++ b/src/console/clients/checker/config.rs @@ -4,7 +4,6 @@ use std::net::SocketAddr; use reqwest::Url as ServiceUrl; use serde::Deserialize; -use url; /// It parses the configuration from a JSON format. /// @@ -88,7 +87,7 @@ impl TryFrom for Configuration { #[cfg(test)] mod tests { - use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + use std::net::{IpAddr, Ipv4Addr}; use super::*; diff --git a/src/core/peer.rs b/src/core/peer.rs index 03489ce30..16aa1fe56 100644 --- a/src/core/peer.rs +++ b/src/core/peer.rs @@ -24,7 +24,6 @@ use std::net::{IpAddr, SocketAddr}; use std::panic::Location; use aquatic_udp_protocol::{AnnounceEvent, NumberOfBytes}; -use serde; use serde::Serialize; use thiserror::Error; diff --git a/src/servers/apis/routes.rs b/src/servers/apis/routes.rs index 227916335..aed3ee19d 100644 --- a/src/servers/apis/routes.rs +++ b/src/servers/apis/routes.rs @@ -6,11 +6,20 @@ //! All the API routes have the `/api` prefix and the version number as the //! first path segment. For example: `/api/v1/torrents`. use std::sync::Arc; +use std::time::Duration; +use axum::http::{HeaderName, HeaderValue}; +use axum::response::Response; use axum::routing::get; use axum::{middleware, Router}; +use hyper::Request; use torrust_tracker_configuration::AccessTokens; 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::v1; use super::v1::context::health_check::handlers::health_check_handler; @@ -32,4 +41,47 @@ pub fn router(tracker: Arc, access_tokens: Arc) -> Router .layer(middleware::from_fn_with_state(state, v1::middlewares::auth::auth)) .route(&format!("{api_url_prefix}/health_check"), get(health_check_handler)) .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(|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: "API", + tracing::Level::INFO, "request", method = %method, uri = %uri, request_id = %request_id); + }) + .on_response(|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: "API", + tracing::Level::INFO, "response", 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)) + } } diff --git a/src/servers/apis/v1/context/auth_key/resources.rs b/src/servers/apis/v1/context/auth_key/resources.rs index f4c7f34ca..99e93aaf9 100644 --- a/src/servers/apis/v1/context/auth_key/resources.rs +++ b/src/servers/apis/v1/context/auth_key/resources.rs @@ -1,5 +1,4 @@ //! API resources for the [`auth_key`](crate::servers::apis::v1::context::auth_key) API context. -use std::convert::From; use serde::{Deserialize, Serialize}; diff --git a/src/servers/http/v1/responses/error.rs b/src/servers/http/v1/responses/error.rs index 606ead3b2..1cc31ad4e 100644 --- a/src/servers/http/v1/responses/error.rs +++ b/src/servers/http/v1/responses/error.rs @@ -13,7 +13,7 @@ //! code. use axum::http::StatusCode; use axum::response::{IntoResponse, Response}; -use serde::{self, Serialize}; +use serde::Serialize; /// `Error` response for the [`HTTP tracker`](crate::servers::http). #[derive(Serialize, Debug, PartialEq)] diff --git a/src/shared/bit_torrent/tracker/http/client/requests/scrape.rs b/src/shared/bit_torrent/tracker/http/client/requests/scrape.rs index d0268d1f8..4fa49eed6 100644 --- a/src/shared/bit_torrent/tracker/http/client/requests/scrape.rs +++ b/src/shared/bit_torrent/tracker/http/client/requests/scrape.rs @@ -1,4 +1,3 @@ -use std::convert::TryFrom; use std::error::Error; use std::fmt::{self}; use std::str::FromStr; diff --git a/src/shared/bit_torrent/tracker/http/client/responses/announce.rs b/src/shared/bit_torrent/tracker/http/client/responses/announce.rs index f68c54482..e75cc6671 100644 --- a/src/shared/bit_torrent/tracker/http/client/responses/announce.rs +++ b/src/shared/bit_torrent/tracker/http/client/responses/announce.rs @@ -1,6 +1,6 @@ use std::net::{IpAddr, Ipv4Addr, SocketAddr}; -use serde::{self, Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; use crate::core::peer::Peer; diff --git a/src/shared/bit_torrent/tracker/http/client/responses/error.rs b/src/shared/bit_torrent/tracker/http/client/responses/error.rs index 12c53a0cf..00befdb54 100644 --- a/src/shared/bit_torrent/tracker/http/client/responses/error.rs +++ b/src/shared/bit_torrent/tracker/http/client/responses/error.rs @@ -1,4 +1,4 @@ -use serde::{self, Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, PartialEq)] pub struct Error { diff --git a/src/shared/bit_torrent/tracker/http/client/responses/scrape.rs b/src/shared/bit_torrent/tracker/http/client/responses/scrape.rs index ee301ee7a..25a2f0a81 100644 --- a/src/shared/bit_torrent/tracker/http/client/responses/scrape.rs +++ b/src/shared/bit_torrent/tracker/http/client/responses/scrape.rs @@ -3,7 +3,7 @@ use std::fmt::Write; use std::str; use serde::ser::SerializeMap; -use serde::{self, Deserialize, Serialize, Serializer}; +use serde::{Deserialize, Serialize, Serializer}; use serde_bencode::value::Value; use crate::shared::bit_torrent::tracker::http::{ByteArray20, InfoHash}; diff --git a/src/shared/crypto/keys.rs b/src/shared/crypto/keys.rs index 92e180996..deb70574f 100644 --- a/src/shared/crypto/keys.rs +++ b/src/shared/crypto/keys.rs @@ -86,8 +86,6 @@ pub mod seeds { #[cfg(test)] mod tests { - use std::convert::TryInto; - use crate::shared::crypto::ephemeral_instance_keys::RANDOM_SEED; use crate::shared::crypto::keys::seeds::detail::ZEROED_TEST_SEED; use crate::shared::crypto::keys::seeds::CURRENT_SEED; diff --git a/tests/servers/http/responses/announce.rs b/tests/servers/http/responses/announce.rs index a57b41c78..968c327eb 100644 --- a/tests/servers/http/responses/announce.rs +++ b/tests/servers/http/responses/announce.rs @@ -1,6 +1,6 @@ use std::net::{IpAddr, Ipv4Addr, SocketAddr}; -use serde::{self, Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; use torrust_tracker::core::peer::Peer; #[derive(Serialize, Deserialize, Debug, PartialEq)] diff --git a/tests/servers/http/responses/error.rs b/tests/servers/http/responses/error.rs index 12c53a0cf..00befdb54 100644 --- a/tests/servers/http/responses/error.rs +++ b/tests/servers/http/responses/error.rs @@ -1,4 +1,4 @@ -use serde::{self, Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, PartialEq)] pub struct Error { diff --git a/tests/servers/http/responses/scrape.rs b/tests/servers/http/responses/scrape.rs index 221ff0a38..eadecb603 100644 --- a/tests/servers/http/responses/scrape.rs +++ b/tests/servers/http/responses/scrape.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use std::str; -use serde::{self, Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; use serde_bencode::value::Value; use crate::servers::http::{ByteArray20, InfoHash};