@@ -19,7 +19,8 @@ use axum::{
19
19
extract:: { self , ws:: WebSocketUpgrade , Extension , Path } ,
20
20
handler:: Handler ,
21
21
http:: {
22
- header, request:: Parts , uri:: PathAndQuery , HeaderValue , Method , Request , StatusCode , Uri ,
22
+ header, request:: Parts , uri:: PathAndQuery , HeaderName , HeaderValue , Method , Request ,
23
+ StatusCode , Uri ,
23
24
} ,
24
25
middleware,
25
26
response:: IntoResponse ,
@@ -44,10 +45,12 @@ use std::{
44
45
use tokio:: sync:: Mutex ;
45
46
use tower_http:: {
46
47
cors:: { self , CorsLayer } ,
48
+ request_id:: { MakeRequestUuid , PropagateRequestIdLayer , SetRequestIdLayer } ,
47
49
services:: ServeDir ,
48
50
set_header:: SetResponseHeader ,
49
51
trace:: TraceLayer ,
50
52
} ;
53
+ use tracing:: { error, error_span, field} ;
51
54
52
55
const ONE_HOUR : Duration = Duration :: from_secs ( 60 * 60 ) ;
53
56
const CORS_CACHE_TIME_TO_LIVE : Duration = ONE_HOUR ;
@@ -113,8 +116,39 @@ pub(crate) async fn serve(config: Config) {
113
116
} ) ;
114
117
}
115
118
119
+ let x_request_id = HeaderName :: from_static ( "x-request-id" ) ;
120
+
116
121
// Basic access logging
117
- app = app. layer ( TraceLayer :: new_for_http ( ) ) ;
122
+ app = app. layer (
123
+ TraceLayer :: new_for_http ( ) . make_span_with ( move |req : & Request < _ > | {
124
+ const REQUEST_ID : & str = "request_id" ;
125
+
126
+ let method = req. method ( ) ;
127
+ let uri = req. uri ( ) ;
128
+ let request_id = req
129
+ . headers ( )
130
+ . get ( & x_request_id)
131
+ . and_then ( |id| id. to_str ( ) . ok ( ) ) ;
132
+
133
+ let span = error_span ! ( "request" , %method, %uri, { REQUEST_ID } = field:: Empty ) ;
134
+
135
+ if let Some ( request_id) = request_id {
136
+ span. record ( REQUEST_ID , field:: display ( request_id) ) ;
137
+ }
138
+
139
+ span
140
+ } ) ,
141
+ ) ;
142
+
143
+ let x_request_id = HeaderName :: from_static ( "x-request-id" ) ;
144
+
145
+ // propagate `x-request-id` headers from request to response
146
+ app = app. layer ( PropagateRequestIdLayer :: new ( x_request_id. clone ( ) ) ) ;
147
+
148
+ app = app. layer ( SetRequestIdLayer :: new (
149
+ x_request_id. clone ( ) ,
150
+ MakeRequestUuid :: default ( ) ,
151
+ ) ) ;
118
152
119
153
let listener = tokio:: net:: TcpListener :: bind ( config. server_socket_addr ( ) )
120
154
. await
@@ -738,6 +772,7 @@ impl IntoResponse for Error {
738
772
. map ( |( _, s, _) | s)
739
773
. reduce ( |l, r| l + ": " + & r)
740
774
. unwrap_or_default ( ) ;
775
+ error ! ( error, "Returning an error to the client" ) ;
741
776
let resp = Json ( ErrorJson { error } ) ;
742
777
let resp = ( StatusCode :: INTERNAL_SERVER_ERROR , resp) ;
743
778
resp. into_response ( )
0 commit comments