Skip to content

Commit b9e000d

Browse files
reeceyangConvex, Inc.
authored andcommitted
add num bytes and bytes per sec to buffering body spans (#44112)
GitOrigin-RevId: 055ddc1051e6aee2d9e56ea0906fd1eff271ce0d
1 parent a086d19 commit b9e000d

File tree

1 file changed

+21
-18
lines changed

1 file changed

+21
-18
lines changed

crates/common/src/http/extract.rs

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,7 @@ use axum::{
1919
};
2020
use bytes::Bytes;
2121
use errors::ErrorMetadata;
22-
use fastrace::{
23-
future::FutureExt as _,
24-
Span,
25-
};
22+
use fastrace::Span;
2623
use futures::TryFutureExt as _;
2724
use http::HeaderMap;
2825
use serde::{
@@ -91,9 +88,26 @@ where
9188

9289
pub 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!
97111
impl<S, T> FromRequest<S> for Json<T>
98112
where
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

Comments
 (0)