@@ -19,7 +19,8 @@ use axum::{
1919 extract:: { self , ws:: WebSocketUpgrade , Extension , Path } ,
2020 handler:: Handler ,
2121 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 ,
2324 } ,
2425 middleware,
2526 response:: IntoResponse ,
@@ -44,10 +45,12 @@ use std::{
4445use tokio:: sync:: Mutex ;
4546use tower_http:: {
4647 cors:: { self , CorsLayer } ,
48+ request_id:: { MakeRequestUuid , PropagateRequestIdLayer , SetRequestIdLayer } ,
4749 services:: ServeDir ,
4850 set_header:: SetResponseHeader ,
4951 trace:: TraceLayer ,
5052} ;
53+ use tracing:: { error, error_span, field} ;
5154
5255const ONE_HOUR : Duration = Duration :: from_secs ( 60 * 60 ) ;
5356const CORS_CACHE_TIME_TO_LIVE : Duration = ONE_HOUR ;
@@ -113,8 +116,39 @@ pub(crate) async fn serve(config: Config) {
113116 } ) ;
114117 }
115118
119+ let x_request_id = HeaderName :: from_static ( "x-request-id" ) ;
120+
116121 // 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+ ) ) ;
118152
119153 let listener = tokio:: net:: TcpListener :: bind ( config. server_socket_addr ( ) )
120154 . await
@@ -738,6 +772,7 @@ impl IntoResponse for Error {
738772 . map ( |( _, s, _) | s)
739773 . reduce ( |l, r| l + ": " + & r)
740774 . unwrap_or_default ( ) ;
775+ error ! ( error, "Returning an error to the client" ) ;
741776 let resp = Json ( ErrorJson { error } ) ;
742777 let resp = ( StatusCode :: INTERNAL_SERVER_ERROR , resp) ;
743778 resp. into_response ( )
0 commit comments