Skip to content

Commit 677e280

Browse files
committed
Make TraceContext::from_headers return Result<Option<Self>>
1 parent 4ccebc9 commit 677e280

File tree

1 file changed

+49
-22
lines changed

1 file changed

+49
-22
lines changed

src/trace/trace_context.rs

Lines changed: 49 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ use rand::Rng;
22
use std::fmt;
33

44
use crate::headers::{HeaderName, HeaderValue, Headers, TRACEPARENT};
5+
use crate::Status;
56

67
/// Extract and apply [Trace-Context](https://w3c.github.io/trace-context/) headers.
78
///
8-
/// ## Examples
9+
/// # Examples
910
///
1011
/// ```
12+
/// # fn main() -> http_types::Result<()> {
13+
/// #
1114
/// use http_types::trace::TraceContext;
1215
///
1316
/// let mut res = http_types::Response::new(200);
@@ -17,14 +20,16 @@ use crate::headers::{HeaderName, HeaderValue, Headers, TRACEPARENT};
1720
/// "00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01"
1821
/// );
1922
///
20-
/// let context = TraceContext::from_headers(&res).unwrap();
23+
/// let context = TraceContext::from_headers(&res)?.unwrap();
2124
///
2225
/// let trace_id = u128::from_str_radix("0af7651916cd43dd8448eb211c80319c", 16);
2326
/// let parent_id = u64::from_str_radix("00f067aa0ba902b7", 16);
2427
///
2528
/// assert_eq!(context.trace_id(), trace_id.unwrap());
2629
/// assert_eq!(context.parent_id(), parent_id.ok());
2730
/// assert_eq!(context.sampled(), true);
31+
/// #
32+
/// # Ok(()) }
2833
/// ```
2934
#[derive(Debug)]
3035
pub struct TraceContext {
@@ -41,7 +46,7 @@ impl TraceContext {
4146
/// By default root TraceContext objects are sampled.
4247
/// To mark it unsampled, call `context.set_sampled(false)`.
4348
///
44-
/// ## Examples
49+
/// # Examples
4550
/// ```
4651
/// use http_types::trace::TraceContext;
4752
///
@@ -64,8 +69,16 @@ impl TraceContext {
6469

6570
/// Create and return TraceContext object based on `traceparent` HTTP header.
6671
///
67-
/// ## Examples
72+
/// # Errors
73+
///
74+
/// This function may error if the header is malformed. An error with a
75+
/// status code of `400: Bad Request` will be generated.
76+
///
77+
/// # Examples
78+
///
6879
/// ```
80+
/// # fn main() -> http_types::Result<()> {
81+
/// #
6982
/// use http_types::trace::TraceContext;
7083
///
7184
/// let mut res = http_types::Response::new(200);
@@ -74,35 +87,43 @@ impl TraceContext {
7487
/// "00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01"
7588
/// );
7689
///
77-
/// let context = TraceContext::from_headers(&res).unwrap();
90+
/// let context = TraceContext::from_headers(&res)?.unwrap();
7891
///
7992
/// let trace_id = u128::from_str_radix("0af7651916cd43dd8448eb211c80319c", 16);
8093
/// let parent_id = u64::from_str_radix("00f067aa0ba902b7", 16);
8194
///
8295
/// assert_eq!(context.trace_id(), trace_id.unwrap());
8396
/// assert_eq!(context.parent_id(), parent_id.ok());
8497
/// assert_eq!(context.sampled(), true);
98+
/// #
99+
/// # Ok(()) }
85100
/// ```
86-
pub fn from_headers(headers: impl AsRef<Headers>) -> Option<Self> {
101+
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
87102
let headers = headers.as_ref();
88103
let mut rng = rand::thread_rng();
89104

90-
let traceparent = headers.get(TRACEPARENT)?;
105+
let traceparent = match headers.get(TRACEPARENT) {
106+
Some(header) => header,
107+
None => return Ok(None),
108+
};
91109
let parts: Vec<&str> = traceparent.as_str().split('-').collect();
92110

93-
Some(Self {
111+
Ok(Some(Self {
94112
id: rng.gen(),
95-
version: u8::from_str_radix(parts[0], 16).ok()?,
96-
trace_id: u128::from_str_radix(parts[1], 16).ok()?,
97-
parent_id: Some(u64::from_str_radix(parts[2], 16).ok()?),
98-
flags: u8::from_str_radix(parts[3], 16).ok()?,
99-
})
113+
version: u8::from_str_radix(parts[0], 16)?,
114+
trace_id: u128::from_str_radix(parts[1], 16).status(400)?,
115+
parent_id: Some(u64::from_str_radix(parts[2], 16).status(400)?),
116+
flags: u8::from_str_radix(parts[3], 16).status(400)?,
117+
}))
100118
}
101119

102120
/// Add the traceparent header to the http headers
103121
///
104-
/// ## Examples
122+
/// # Examples
123+
///
105124
/// ```
125+
/// # fn main() -> http_types::Result<()> {
126+
/// #
106127
/// use http_types::trace::TraceContext;
107128
/// use http_types::{Request, Response, Url, Method};
108129
///
@@ -112,16 +133,18 @@ impl TraceContext {
112133
/// "00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01"
113134
/// );
114135
///
115-
/// let parent = TraceContext::from_headers(&req).unwrap();
136+
/// let parent = TraceContext::from_headers(&req)?.unwrap();
116137
///
117138
/// let mut res = Response::new(200);
118139
/// parent.apply(&mut res);
119140
///
120-
/// let child = TraceContext::from_headers(&res).unwrap();
141+
/// let child = TraceContext::from_headers(&res)?.unwrap();
121142
///
122143
/// assert_eq!(child.version(), parent.version());
123144
/// assert_eq!(child.trace_id(), parent.trace_id());
124145
/// assert_eq!(child.parent_id(), Some(parent.id()));
146+
/// #
147+
/// # Ok(()) }
125148
/// ```
126149
pub fn apply(&self, mut headers: impl AsMut<Headers>) {
127150
let headers = headers.as_mut();
@@ -182,24 +205,28 @@ impl TraceContext {
182205

183206
/// Returns true if the trace is sampled
184207
///
185-
/// ## Examples
208+
/// # Examples
186209
///
187210
/// ```
211+
/// # fn main() -> http_types::Result<()> {
212+
/// #
188213
/// use http_types::trace::TraceContext;
189214
/// use http_types::Response;
190215
///
191216
/// let mut res = Response::new(200);
192217
/// res.insert_header("traceparent", "00-00000000000000000000000000000001-0000000000000002-01");
193-
/// let context = TraceContext::from_headers(&res).unwrap();
218+
/// let context = TraceContext::from_headers(&res)?.unwrap();
194219
/// assert_eq!(context.sampled(), true);
220+
/// #
221+
/// # Ok(()) }
195222
/// ```
196223
pub fn sampled(&self) -> bool {
197224
(self.flags & 0b00000001) == 1
198225
}
199226

200227
/// Change sampled flag
201228
///
202-
/// ## Examples
229+
/// # Examples
203230
///
204231
/// ```
205232
/// use http_types::trace::TraceContext;
@@ -233,7 +260,7 @@ mod test {
233260
fn default() -> crate::Result<()> {
234261
let mut headers = crate::Headers::new();
235262
headers.insert(TRACEPARENT, "00-01-deadbeef-00");
236-
let context = TraceContext::from_headers(&mut headers).unwrap();
263+
let context = TraceContext::from_headers(&mut headers)?.unwrap();
237264
assert_eq!(context.version(), 0);
238265
assert_eq!(context.trace_id(), 1);
239266
assert_eq!(context.parent_id().unwrap(), 3735928559);
@@ -256,7 +283,7 @@ mod test {
256283
fn not_sampled() -> crate::Result<()> {
257284
let mut headers = crate::Headers::new();
258285
headers.insert(TRACEPARENT, "00-01-02-00");
259-
let context = TraceContext::from_headers(&mut headers).unwrap();
286+
let context = TraceContext::from_headers(&mut headers)?.unwrap();
260287
assert_eq!(context.sampled(), false);
261288
Ok(())
262289
}
@@ -265,7 +292,7 @@ mod test {
265292
fn sampled() -> crate::Result<()> {
266293
let mut headers = crate::Headers::new();
267294
headers.insert(TRACEPARENT, "00-01-02-01");
268-
let context = TraceContext::from_headers(&mut headers).unwrap();
295+
let context = TraceContext::from_headers(&mut headers)?.unwrap();
269296
assert_eq!(context.sampled(), true);
270297
Ok(())
271298
}

0 commit comments

Comments
 (0)