@@ -19,10 +19,7 @@ use axum::{
1919} ;
2020use bytes:: Bytes ;
2121use errors:: ErrorMetadata ;
22- use fastrace:: {
23- future:: FutureExt as _,
24- Span ,
25- } ;
22+ use fastrace:: Span ;
2623use futures:: TryFutureExt as _;
2724use http:: HeaderMap ;
2825use serde:: {
9188
9289pub struct Json < T > ( pub T ) ;
9390
91+ async fn buffer_body < S : Send + Sync > ( req : Request , state : & S ) -> anyhow:: Result < Bytes > {
92+ let span = Span :: enter_with_local_parent ( "buffering_body" ) ;
93+ let bytes = Bytes :: from_request ( req, state)
94+ . await
95+ . map_err ( |e| anyhow:: anyhow!( ErrorMetadata :: bad_request( "BadJsonBody" , e. body_text( ) ) ) ) ?;
96+ if let Some ( duration) = span. elapsed ( ) {
97+ span. add_property ( || ( "num_bytes" , bytes. len ( ) . to_string ( ) ) ) ;
98+ span. add_property ( || {
99+ (
100+ "megabytes_per_sec" ,
101+ format ! ( "{:.3}" , bytes. len( ) as f64 / ( duration. as_secs_f64( ) * 1e6 ) ) ,
102+ )
103+ } ) ;
104+ }
105+ Ok ( bytes)
106+ }
107+
94108/// Fork of axum::Json that uses HttpResponseError instead of JsonRejection to
95109/// make sure we get propper logging / error reporting and integrates with our
96- /// tracing framework.
110+ /// tracing framework. Note that we also implement OptionalFromRequest below!
97111impl < S , T > FromRequest < S > for Json < T >
98112where
99113 T : DeserializeOwned ,
@@ -109,12 +123,7 @@ where
109123 ) ) ;
110124 return Err ( err. into ( ) ) ;
111125 }
112- let bytes = Bytes :: from_request ( req, state)
113- . in_span ( Span :: enter_with_local_parent ( "buffering_body" ) )
114- . await
115- . map_err ( |e| {
116- anyhow:: anyhow!( ErrorMetadata :: bad_request( "BadJsonBody" , e. body_text( ) ) )
117- } ) ?;
126+ let bytes = buffer_body ( req, state) . await ?;
118127
119128 let t = {
120129 let _span = Span :: enter_with_local_parent ( "parse_json" ) ;
@@ -140,13 +149,7 @@ where
140149 if !json_content_type ( req. headers ( ) ) {
141150 return Ok ( None ) ;
142151 }
143- let bytes = Bytes :: from_request ( req, state)
144- . in_span ( Span :: enter_with_local_parent ( "buffering_body" ) )
145- . await
146- . map_err ( |e| {
147- anyhow:: anyhow!( ErrorMetadata :: bad_request( "BadJsonBody" , e. body_text( ) ) )
148- } ) ?;
149-
152+ let bytes = buffer_body ( req, state) . await ?;
150153 let t = {
151154 let _span = Span :: enter_with_local_parent ( "parse_json" ) ;
152155 #[ allow( clippy:: disallowed_types) ]
0 commit comments