1
1
//! HTTP server routes for version `v1`.
2
2
use std:: sync:: Arc ;
3
+ use std:: time:: Duration ;
3
4
5
+ use axum:: http:: { HeaderName , HeaderValue } ;
6
+ use axum:: response:: Response ;
4
7
use axum:: routing:: get;
5
8
use axum:: Router ;
6
9
use axum_client_ip:: SecureClientIpSource ;
10
+ use hyper:: Request ;
7
11
use tower_http:: compression:: CompressionLayer ;
12
+ use tower_http:: propagate_header:: PropagateHeaderLayer ;
13
+ use tower_http:: request_id:: { MakeRequestId , RequestId , SetRequestIdLayer } ;
14
+ use tower_http:: trace:: { DefaultMakeSpan , TraceLayer } ;
15
+ use tracing:: { Level , Span } ;
16
+ use uuid:: Uuid ;
8
17
9
18
use super :: handlers:: { announce, health_check, scrape} ;
10
19
use crate :: core:: Tracker ;
@@ -27,4 +36,47 @@ pub fn router(tracker: Arc<Tracker>) -> Router {
27
36
// Add extension to get the client IP from the connection info
28
37
. layer ( SecureClientIpSource :: ConnectInfo . into_extension ( ) )
29
38
. layer ( CompressionLayer :: new ( ) )
39
+ . layer ( SetRequestIdLayer :: x_request_id ( RequestIdGenerator ) )
40
+ . layer ( PropagateHeaderLayer :: new ( HeaderName :: from_static ( "x-request-id" ) ) )
41
+ . layer (
42
+ TraceLayer :: new_for_http ( )
43
+ . make_span_with ( DefaultMakeSpan :: new ( ) . level ( Level :: INFO ) )
44
+ . on_request ( |request : & Request < axum:: body:: Body > , _span : & Span | {
45
+ let method = request. method ( ) . to_string ( ) ;
46
+ let uri = request. uri ( ) . to_string ( ) ;
47
+ let request_id = request
48
+ . headers ( )
49
+ . get ( "x-request-id" )
50
+ . map ( |v| v. to_str ( ) . unwrap_or_default ( ) )
51
+ . unwrap_or_default ( ) ;
52
+
53
+ tracing:: span!(
54
+ target: "HTTP TRACKER" ,
55
+ tracing:: Level :: INFO , "request" , method = %method, uri = %uri, request_id = %request_id) ;
56
+ } )
57
+ . on_response ( |response : & Response , latency : Duration , _span : & Span | {
58
+ let status_code = response. status ( ) ;
59
+ let request_id = response
60
+ . headers ( )
61
+ . get ( "x-request-id" )
62
+ . map ( |v| v. to_str ( ) . unwrap_or_default ( ) )
63
+ . unwrap_or_default ( ) ;
64
+ let latency_ms = latency. as_millis ( ) ;
65
+
66
+ tracing:: span!(
67
+ target: "HTTP TRACKER" ,
68
+ tracing:: Level :: INFO , "response" , latency = %latency_ms, status = %status_code, request_id = %request_id) ;
69
+ } ) ,
70
+ )
71
+ . layer ( SetRequestIdLayer :: x_request_id ( RequestIdGenerator ) )
72
+ }
73
+
74
+ #[ derive( Clone , Default ) ]
75
+ struct RequestIdGenerator ;
76
+
77
+ impl MakeRequestId for RequestIdGenerator {
78
+ fn make_request_id < B > ( & mut self , _request : & Request < B > ) -> Option < RequestId > {
79
+ let id = HeaderValue :: from_str ( & Uuid :: new_v4 ( ) . to_string ( ) ) . expect ( "UUID is a valid HTTP header value" ) ;
80
+ Some ( RequestId :: new ( id) )
81
+ }
30
82
}
0 commit comments