Skip to content

Commit b894439

Browse files
committed
feat: add debug spans for decoding requests
Closes: hyperium#1759
1 parent d312dcc commit b894439

File tree

2 files changed

+65
-17
lines changed

2 files changed

+65
-17
lines changed

tonic/src/codec/compression.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,7 @@ impl CompressionEncoding {
158158
}
159159

160160
#[allow(missing_docs)]
161-
#[cfg(any(feature = "gzip", feature = "zstd"))]
162-
pub(crate) fn as_str(&self) -> &'static str {
161+
pub(crate) const fn as_str(&self) -> &'static str {
163162
match self {
164163
#[cfg(feature = "gzip")]
165164
CompressionEncoding::Gzip => "gzip",
@@ -169,11 +168,11 @@ impl CompressionEncoding {
169168
}
170169

171170
#[cfg(any(feature = "gzip", feature = "zstd"))]
172-
pub(crate) fn into_header_value(self) -> http::HeaderValue {
171+
pub(crate) const fn into_header_value(self) -> http::HeaderValue {
173172
http::HeaderValue::from_static(self.as_str())
174173
}
175174

176-
pub(crate) fn encodings() -> &'static [Self] {
175+
pub(crate) const fn encodings() -> &'static [Self] {
177176
&[
178177
#[cfg(feature = "gzip")]
179178
CompressionEncoding::Gzip,

tonic/src/codec/decode.rs

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,43 @@ impl<T> Unpin for Streaming<T> {}
3838

3939
#[derive(Debug, Clone)]
4040
enum State {
41-
ReadHeader,
41+
ReadHeader {
42+
span: Option<tracing::Span>,
43+
},
4244
ReadBody {
45+
span: tracing::Span,
4346
compression: Option<CompressionEncoding>,
4447
len: usize,
4548
},
46-
Error(Status),
49+
Error(Box<Status>),
50+
}
51+
52+
impl State {
53+
fn read_header() -> Self {
54+
Self::ReadHeader { span: None }
55+
}
56+
57+
fn read_body(compression: Option<CompressionEncoding>, len: usize) -> Self {
58+
let span = tracing::debug_span!(
59+
"read_body",
60+
compression = compression.map(|c| c.as_str()),
61+
compressed.bytes = compression.is_some().then_some(len),
62+
uncompressed.bytes = compression.is_none().then_some(len),
63+
);
64+
Self::ReadBody {
65+
span,
66+
compression,
67+
len,
68+
}
69+
}
70+
71+
fn span(&self) -> Option<&tracing::Span> {
72+
match self {
73+
Self::ReadHeader { span } => span.as_ref(),
74+
Self::ReadBody { span, .. } => Some(span),
75+
Self::Error(_) => None,
76+
}
77+
}
4778
}
4879

4980
#[derive(Debug, PartialEq, Eq)]
@@ -125,7 +156,7 @@ impl<T> Streaming<T> {
125156
.map_frame(|frame| frame.map_data(|mut buf| buf.copy_to_bytes(buf.remaining())))
126157
.map_err(|err| Status::map_error(err.into()))
127158
.boxed_unsync(),
128-
state: State::ReadHeader,
159+
state: State::read_header(),
129160
direction,
130161
buf: BytesMut::with_capacity(buffer_size),
131162
trailers: None,
@@ -142,7 +173,15 @@ impl StreamingInner {
142173
&mut self,
143174
buffer_settings: BufferSettings,
144175
) -> Result<Option<DecodeBuf<'_>>, Status> {
145-
if let State::ReadHeader = self.state {
176+
if let State::ReadHeader { span } = &mut self.state {
177+
let span = span.get_or_insert_with(|| {
178+
tracing::debug_span!(
179+
"read_header",
180+
compression = tracing::field::Empty,
181+
body.bytes = tracing::field::Empty,
182+
)
183+
});
184+
let _guard = span.enter();
146185
if self.buf.remaining() < HEADER_SIZE {
147186
return Ok(None);
148187
}
@@ -151,7 +190,8 @@ impl StreamingInner {
151190
0 => None,
152191
1 => {
153192
{
154-
if self.encoding.is_some() {
193+
if let Some(ce) = self.encoding {
194+
span.record("compression", ce.as_str());
155195
self.encoding
156196
} else {
157197
// https://grpc.github.io/grpc/core/md_doc_compression.html
@@ -177,6 +217,7 @@ impl StreamingInner {
177217
};
178218

179219
let len = self.buf.get_u32() as usize;
220+
span.record("body.bytes", len);
180221
let limit = self
181222
.max_message_size
182223
.unwrap_or(DEFAULT_MAX_RECV_MESSAGE_SIZE);
@@ -191,14 +232,19 @@ impl StreamingInner {
191232
}
192233

193234
self.buf.reserve(len);
235+
drop(_guard);
194236

195-
self.state = State::ReadBody {
196-
compression: compression_encoding,
197-
len,
198-
}
237+
self.state = State::read_body(compression_encoding, len)
199238
}
200239

201-
if let State::ReadBody { len, compression } = self.state {
240+
if let State::ReadBody {
241+
len,
242+
span,
243+
compression,
244+
} = &self.state
245+
{
246+
let (len, compression) = (*len, *compression);
247+
let _guard = span.enter();
202248
// if we haven't read enough of the message then return and keep
203249
// reading
204250
if self.buf.remaining() < len || self.buf.len() < len {
@@ -228,6 +274,7 @@ impl StreamingInner {
228274
return Err(Status::new(Code::Internal, message));
229275
}
230276
let decompressed_len = self.decompress_buf.len();
277+
span.record("uncompressed.bytes", decompressed_len);
231278
DecodeBuf::new(&mut self.decompress_buf, decompressed_len)
232279
} else {
233280
DecodeBuf::new(&mut self.buf, len)
@@ -241,14 +288,16 @@ impl StreamingInner {
241288

242289
// Returns Some(()) if data was found or None if the loop in `poll_next` should break
243290
fn poll_frame(&mut self, cx: &mut Context<'_>) -> Poll<Result<Option<()>, Status>> {
291+
let _guard = self.state.span().map(|s| s.enter());
244292
let chunk = match ready!(Pin::new(&mut self.body).poll_frame(cx)) {
245293
Some(Ok(d)) => Some(d),
246294
Some(Err(status)) => {
247295
if self.direction == Direction::Request && status.code() == Code::Cancelled {
248296
return Poll::Ready(Ok(None));
249297
}
250298

251-
let _ = std::mem::replace(&mut self.state, State::Error(status.clone()));
299+
drop(_guard);
300+
let _ = std::mem::replace(&mut self.state, State::Error(Box::new(status.clone())));
252301
debug!("decoder inner stream error: {:?}", status);
253302
return Poll::Ready(Err(status));
254303
}
@@ -378,7 +427,7 @@ impl<T> Streaming<T> {
378427
match self.inner.decode_chunk(self.decoder.buffer_settings())? {
379428
Some(mut decode_buf) => match self.decoder.decode(&mut decode_buf)? {
380429
Some(msg) => {
381-
self.inner.state = State::ReadHeader;
430+
self.inner.state = State::read_header();
382431
Ok(Some(msg))
383432
}
384433
None => Ok(None),
@@ -394,7 +443,7 @@ impl<T> Stream for Streaming<T> {
394443
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
395444
loop {
396445
if let State::Error(status) = &self.inner.state {
397-
return Poll::Ready(Some(Err(status.clone())));
446+
return Poll::Ready(Some(Err(*status.clone())));
398447
}
399448

400449
if let Some(item) = self.decode_chunk()? {

0 commit comments

Comments
 (0)