Skip to content

Commit

Permalink
Refactor span ID and trace ID using newtype pattern (#73)
Browse files Browse the repository at this point in the history
* Refactor span ID and trace ID using newtype pattern

Wraps usages of span ID (u64) and trace ID (u128) in single-field tuple structs in
order to enforce intention when passing around values of these types.
Adds the "SpanId::invalid()" and "TraceId::invalid()" methods for
conveniently creating zero-valued instances of both types.

* Add methods to convert between SpanId, TraceId, and corresponding uints

Adds the from_u64 and to_u64 methods to SpanId and the from_u128 and
to_u128 methods to TraceId. Facilitates straightforward conversion
between the wrapper structs and their wrapped uint types.
  • Loading branch information
Sam Naser authored Mar 6, 2020
1 parent 51e096f commit b31b674
Show file tree
Hide file tree
Showing 15 changed files with 172 additions and 91 deletions.
6 changes: 3 additions & 3 deletions opentelemetry-jaeger/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,14 +332,14 @@ impl Into<jaeger::Log> for api::Event {
impl Into<jaeger::Span> for Arc<trace::SpanData> {
/// Convert spans to jaeger thrift span for exporting.
fn into(self) -> jaeger::Span {
let trace_id = self.context.trace_id();
let trace_id = self.context.trace_id().to_u128();
let trace_id_high = (trace_id >> 64) as i64;
let trace_id_low = trace_id as i64;
jaeger::Span {
trace_id_low,
trace_id_high,
span_id: self.context.span_id() as i64,
parent_span_id: self.parent_span_id as i64,
span_id: self.context.span_id().to_u64() as i64,
parent_span_id: self.parent_span_id.to_u64() as i64,
operation_name: self.name.clone(),
references: links_to_references(&self.links),
flags: self.context.trace_flags() as i32,
Expand Down
2 changes: 1 addition & 1 deletion src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub use trace::{
provider::Provider,
sampler::{Sampler, SamplingDecision, SamplingResult},
span::{Span, SpanKind, SpanStatus},
span_context::{SpanContext, TRACE_FLAGS_UNUSED, TRACE_FLAG_SAMPLED},
span_context::{SpanContext, SpanId, TraceId, TRACE_FLAGS_UNUSED, TRACE_FLAG_SAMPLED},
span_processor::SpanProcessor,
trace_context_propagator::TraceContextPropagator,
tracer::{Tracer, TracerGenerics},
Expand Down
26 changes: 17 additions & 9 deletions src/api/propagation/binary_propagator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,9 @@ impl BinaryFormat for BinaryPropagator {
if !context.is_valid() {
return res;
}

res[2..18].copy_from_slice(&context.trace_id().to_be_bytes());
res[2..18].copy_from_slice(&context.trace_id().to_u128().to_be_bytes());
res[18] = 1;
res[19..27].copy_from_slice(&context.span_id().to_be_bytes());
res[19..27].copy_from_slice(&context.span_id().to_u64().to_be_bytes());
res[27] = 2;
res[28] = context.trace_flags();

Expand Down Expand Up @@ -69,7 +68,12 @@ impl BinaryFormat for BinaryPropagator {
trace_flags = b[1]
}

let span_context = api::SpanContext::new(trace_id, span_id, trace_flags, true);
let span_context = api::SpanContext::new(
api::TraceId::from_u128(trace_id),
api::SpanId::from_u64(span_id),
trace_flags,
true,
);

if span_context.is_valid() {
span_context
Expand All @@ -88,13 +92,17 @@ mod test {
fn to_bytes_data() -> Vec<(api::SpanContext, [u8; 29])> {
vec![
// Context with sampled
(api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 1, true), [
(api::SpanContext::new(
api::TraceId::from_u128(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736),
api::SpanId::from_u64(0x00f0_67aa_0ba9_02b7), 1, true), [
0x00, 0x00, 0x4b, 0xf9, 0x2f, 0x35, 0x77, 0xb3, 0x4d, 0xa6, 0xa3, 0xce, 0x92, 0x9d, 0x0e, 0x0e, 0x47, 0x36,
0x01, 0x00, 0xf0, 0x67, 0xaa, 0x0b, 0xa9, 0x02, 0xb7,
0x02, 0x01,
]),
// Context without sampled
(api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 0, true), [
(api::SpanContext::new(
api::TraceId::from_u128(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736),
api::SpanId::from_u64(0x00f0_67aa_0ba9_02b7), 0, true), [
0x00, 0x00, 0x4b, 0xf9, 0x2f, 0x35, 0x77, 0xb3, 0x4d, 0xa6, 0xa3, 0xce, 0x92, 0x9d, 0x0e, 0x0e, 0x47, 0x36,
0x01, 0x00, 0xf0, 0x67, 0xaa, 0x0b, 0xa9, 0x02, 0xb7,
0x02, 0x00,
Expand All @@ -108,19 +116,19 @@ mod test {
fn from_bytes_data() -> Vec<(api::SpanContext, Vec<u8>)> {
vec![
// Future version of the proto
(api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 1, true), vec![
(api::SpanContext::new(api::TraceId::from_u128(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736), api::SpanId::from_u64(0x00f0_67aa_0ba9_02b7), 1, true), vec![
0x02, 0x00, 0x4b, 0xf9, 0x2f, 0x35, 0x77, 0xb3, 0x4d, 0xa6, 0xa3, 0xce, 0x92, 0x9d, 0x0e, 0x0e, 0x47, 0x36,
0x01, 0x00, 0xf0, 0x67, 0xaa, 0x0b, 0xa9, 0x02, 0xb7,
0x02, 0x01,
]),
// current version with sampled
(api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 1, true), vec![
(api::SpanContext::new(api::TraceId::from_u128(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736), api::SpanId::from_u64(0x00f0_67aa_0ba9_02b7), 1, true), vec![
0x02, 0x00, 0x4b, 0xf9, 0x2f, 0x35, 0x77, 0xb3, 0x4d, 0xa6, 0xa3, 0xce, 0x92, 0x9d, 0x0e, 0x0e, 0x47, 0x36,
0x01, 0x00, 0xf0, 0x67, 0xaa, 0x0b, 0xa9, 0x02, 0xb7,
0x02, 0x01,
]),
// valid context without option
(api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 0, true), vec![
(api::SpanContext::new(api::TraceId::from_u128(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736), api::SpanId::from_u64(0x00f0_67aa_0ba9_02b7), 0, true), vec![
0x00, 0x00, 0x4b, 0xf9, 0x2f, 0x35, 0x77, 0xb3, 0x4d, 0xa6, 0xa3, 0xce, 0x92, 0x9d, 0x0e, 0x0e, 0x47, 0x36,
0x01, 0x00, 0xf0, 0x67, 0xaa, 0x0b, 0xa9, 0x02, 0xb7,
]),
Expand Down
4 changes: 2 additions & 2 deletions src/api/propagation/noop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ impl api::HttpTextFormat for NoopTextFormat {

/// Always returns invalid span contexts
fn extract(&self, _carrier: &dyn api::Carrier) -> api::SpanContext {
api::SpanContext::new(0, 0, 0, false)
api::SpanContext::new(api::TraceId::invalid(), api::SpanId::invalid(), 0, false)
}
}

Expand All @@ -31,6 +31,6 @@ impl api::BinaryFormat for NoopBinaryFormat {

/// Always returns invalid span contexts
fn from_bytes(&self, _bytes: Vec<u8>) -> api::SpanContext {
api::SpanContext::new(0, 0, 0, false)
api::SpanContext::new(api::TraceId::invalid(), api::SpanId::invalid(), 0, false)
}
}
58 changes: 32 additions & 26 deletions src/api/trace/b3_propagator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ impl B3Propagator {
}

/// Extract trace id from hex encoded &str value.
fn extract_trace_id(&self, trace_id: &str) -> Result<u128, std::num::ParseIntError> {
u128::from_str_radix(trace_id, 16)
fn extract_trace_id(&self, trace_id: &str) -> Result<api::TraceId, std::num::ParseIntError> {
u128::from_str_radix(trace_id, 16).map(api::TraceId::from_u128)
}

/// Extract span id from hex encoded &str value.
fn extract_span_id(&self, span_id: &str) -> Result<u64, std::num::ParseIntError> {
u64::from_str_radix(span_id, 16)
fn extract_span_id(&self, span_id: &str) -> Result<api::SpanId, std::num::ParseIntError> {
u64::from_str_radix(span_id, 16).map(api::SpanId::from_u64)
}

/// Extract sampled state from encoded &str value
Expand Down Expand Up @@ -136,14 +136,20 @@ impl api::HttpTextFormat for B3Propagator {
B3_SINGLE_HEADER,
format!(
"{:032x}-{:016x}-{:01}",
context.trace_id(),
context.span_id(),
context.trace_id().to_u128(),
context.span_id().to_u64(),
sampled
),
);
} else {
carrier.set(B3_TRACE_ID_HEADER, format!("{:032x}", context.trace_id()));
carrier.set(B3_SPAN_ID_HEADER, format!("{:016x}", context.span_id()));
carrier.set(
B3_TRACE_ID_HEADER,
format!("{:032x}", context.trace_id().to_u128()),
);
carrier.set(
B3_SPAN_ID_HEADER,
format!("{:016x}", context.span_id().to_u64()),
);

let sampled = if context.is_sampled() { "1" } else { "0" };
carrier.set(B3_SAMPLED_HEADER, sampled.to_string())
Expand All @@ -169,17 +175,18 @@ impl api::HttpTextFormat for B3Propagator {
#[cfg(test)]
mod test {
use super::*;
use crate::api::trace::span_context::{SpanId, TraceId};
use crate::api::HttpTextFormat;
use std::collections::HashMap;

#[rustfmt::skip]
fn single_header_extract_data() -> Vec<(&'static str, api::SpanContext)> {
vec![
("4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7", api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 0, true)),
("4bf92f3577b34da6a3ce929d0e0e4736-f067aa0ba902b7-0", api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 0, true)),
("4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-1", api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 1, true)),
("4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-d", api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 1, true)),
("4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-1-00000000000000cd", api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 1, true)),
("4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7", api::SpanContext::new(TraceId::from_u128(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736), SpanId::from_u64(0x00f0_67aa_0ba9_02b7), 0, true)),
("4bf92f3577b34da6a3ce929d0e0e4736-f067aa0ba902b7-0", api::SpanContext::new(TraceId::from_u128(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736), SpanId::from_u64(0x00f0_67aa_0ba9_02b7), 0, true)),
("4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-1", api::SpanContext::new(TraceId::from_u128(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736), SpanId::from_u64(0x00f0_67aa_0ba9_02b7), 1, true)),
("4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-d", api::SpanContext::new(TraceId::from_u128(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736), SpanId::from_u64(0x00f0_67aa_0ba9_02b7), 1, true)),
("4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-1-00000000000000cd", api::SpanContext::new(TraceId::from_u128(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736), SpanId::from_u64(0x00f0_67aa_0ba9_02b7), 1, true)),
("0", api::SpanContext::empty_context()),
]
}
Expand All @@ -188,32 +195,31 @@ mod test {
#[allow(clippy::type_complexity)]
fn multi_header_extract_data() -> Vec<((Option<&'static str>, Option<&'static str>, Option<&'static str>, Option<&'static str>, Option<&'static str>), api::SpanContext)> {
vec![
((Some("4bf92f3577b34da6a3ce929d0e0e4736"), Some("00f067aa0ba902b7"), None, None, None), api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 0, true)),
((Some("4bf92f3577b34da6a3ce929d0e0e4736"), Some("00f067aa0ba902b7"), Some("0"), None, None), api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 0, true)),
((Some("4bf92f3577b34da6a3ce929d0e0e4736"), Some("00f067aa0ba902b7"), Some("1"), None, None), api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 1, true)),
((Some("4bf92f3577b34da6a3ce929d0e0e4736"), Some("00f067aa0ba902b7"), Some("true"), None, None), api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 1, true)),
((Some("4bf92f3577b34da6a3ce929d0e0e4736"), Some("00f067aa0ba902b7"), None, Some("1"), None), api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 1, true)),
((Some("4bf92f3577b34da6a3ce929d0e0e4736"), Some("00f067aa0ba902b7"), Some("0"), Some("1"), None), api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 1, true)),
((Some("4bf92f3577b34da6a3ce929d0e0e4736"), Some("00f067aa0ba902b7"), Some("1"), None, Some("00f067aa0ba90200")), api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 1, true)),
((Some("4bf92f3577b34da6a3ce929d0e0e4736"), Some("00f067aa0ba902b7"), None, None, None), api::SpanContext::new(TraceId::from_u128(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736), SpanId::from_u64(0x00f0_67aa_0ba9_02b7), 0, true)),
((Some("4bf92f3577b34da6a3ce929d0e0e4736"), Some("00f067aa0ba902b7"), Some("0"), None, None), api::SpanContext::new(TraceId::from_u128(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736), SpanId::from_u64(0x00f0_67aa_0ba9_02b7), 0, true)),
((Some("4bf92f3577b34da6a3ce929d0e0e4736"), Some("00f067aa0ba902b7"), Some("1"), None, None), api::SpanContext::new(TraceId::from_u128(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736), SpanId::from_u64(0x00f0_67aa_0ba9_02b7), 1, true)),
((Some("4bf92f3577b34da6a3ce929d0e0e4736"), Some("00f067aa0ba902b7"), Some("true"), None, None), api::SpanContext::new(TraceId::from_u128(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736), SpanId::from_u64(0x00f0_67aa_0ba9_02b7), 1, true)),
((Some("4bf92f3577b34da6a3ce929d0e0e4736"), Some("00f067aa0ba902b7"), None, Some("1"), None), api::SpanContext::new(TraceId::from_u128(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736), SpanId::from_u64(0x00f0_67aa_0ba9_02b7), 1, true)),
((Some("4bf92f3577b34da6a3ce929d0e0e4736"), Some("00f067aa0ba902b7"), Some("1"), None, Some("00f067aa0ba90200")), api::SpanContext::new(TraceId::from_u128(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736), SpanId::from_u64(0x00f0_67aa_0ba9_02b7), 1, true)),
((None, None, Some("0"), None, None), api::SpanContext::empty_context()),
]
}

#[rustfmt::skip]
fn single_header_inject_data() -> Vec<(&'static str, api::SpanContext)> {
vec![
("4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-1", api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 1, true)),
("4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-0", api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 0, true)),
("4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-1", api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 0xff, true)),
("4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-1", api::SpanContext::new(TraceId::from_u128(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736), SpanId::from_u64(0x00f0_67aa_0ba9_02b7), 1, true)),
("4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-0", api::SpanContext::new(TraceId::from_u128(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736), SpanId::from_u64(0x00f0_67aa_0ba9_02b7), 0, true)),
("4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-1", api::SpanContext::new(TraceId::from_u128(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736), SpanId::from_u64(0x00f0_67aa_0ba9_02b7), 0xff, true)),
]
}

#[rustfmt::skip]
fn multi_header_inject_data() -> Vec<(&'static str, &'static str, &'static str, api::SpanContext)> {
vec![
("4bf92f3577b34da6a3ce929d0e0e4736", "00f067aa0ba902b7", "1", api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 1, true)),
("4bf92f3577b34da6a3ce929d0e0e4736", "00f067aa0ba902b7", "0", api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 0, true)),
("4bf92f3577b34da6a3ce929d0e0e4736", "00f067aa0ba902b7", "1", api::SpanContext::new(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736, 0x00f0_67aa_0ba9_02b7, 0xff, true)),
("4bf92f3577b34da6a3ce929d0e0e4736", "00f067aa0ba902b7", "1", api::SpanContext::new(TraceId::from_u128(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736), SpanId::from_u64(0x00f0_67aa_0ba9_02b7), 1, true)),
("4bf92f3577b34da6a3ce929d0e0e4736", "00f067aa0ba902b7", "0", api::SpanContext::new(TraceId::from_u128(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736), SpanId::from_u64(0x00f0_67aa_0ba9_02b7), 0, true)),
("4bf92f3577b34da6a3ce929d0e0e4736", "00f067aa0ba902b7", "1", api::SpanContext::new(TraceId::from_u128(0x4bf9_2f35_77b3_4da6_a3ce_929d_0e0e_4736), SpanId::from_u64(0x00f0_67aa_0ba9_02b7), 0xff, true)),
]
}

Expand Down
9 changes: 7 additions & 2 deletions src/api/trace/noop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,12 @@ impl NoopSpan {
/// Creates a new `NoopSpan` instance.
pub fn new() -> Self {
NoopSpan {
span_context: api::SpanContext::new(0, 0, 0, false),
span_context: api::SpanContext::new(
api::TraceId::invalid(),
api::SpanId::invalid(),
0,
false,
),
}
}
}
Expand Down Expand Up @@ -126,7 +131,7 @@ impl api::Tracer for NoopTracer {
}

/// Ignores active span state.
fn mark_span_as_inactive(&self, _span_id: u64) {
fn mark_span_as_inactive(&self, _span_id: api::SpanId) {
// Noop
}

Expand Down
4 changes: 2 additions & 2 deletions src/api/trace/sampler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ pub trait Sampler: Send + Sync + std::fmt::Debug {
fn should_sample(
&self,
parent_context: Option<&api::SpanContext>,
trace_id: u128,
span_id: u64,
trace_id: api::TraceId,
span_id: api::SpanId,
name: &str,
span_kind: &api::SpanKind,
attributes: &[api::KeyValue],
Expand Down
60 changes: 53 additions & 7 deletions src/api/trace/span_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,70 @@ pub const TRACE_FLAG_SAMPLED: u8 = TRACE_FLAGS_BIT_MASK_SAMPLED;
/// Useful for extracting trace context
pub const TRACE_FLAGS_UNUSED: u8 = TRACE_FLAGS_BIT_MASK_UNUSED;

/// TraceId is an 16-byte value which uniquely identifies a given trace
/// The actual `u128` value is wrapped in a tuple struct in order to leverage the newtype pattern
#[cfg_attr(feature = "serialize", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash)]
pub struct TraceId(u128);

impl TraceId {
/// Construct a new invalid (zero-valued) TraceId
pub fn invalid() -> Self {
TraceId(0)
}

/// Convert from u128 to TraceId
pub fn from_u128(item: u128) -> Self {
TraceId(item)
}

/// Convert from TraceId to u128
pub fn to_u128(self) -> u128 {
self.0
}
}

/// SpanId is an 8-byte value which uniquely identifies a given span within a trace
/// The actual `u64` value is wrapped in a tuple struct in order to leverage the newtype pattern
#[cfg_attr(feature = "serialize", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash)]
pub struct SpanId(u64);

impl SpanId {
/// Construct a new invalid (zero-valued) SpanId
pub fn invalid() -> Self {
SpanId(0)
}

/// Convert from u64 to SpanId
pub fn from_u64(item: u64) -> Self {
SpanId(item)
}

/// Convert from SpanId to u64
pub fn to_u64(self) -> u64 {
self.0
}
}

/// Immutable portion of a `Span` which can be serialized and propagated.
#[cfg_attr(feature = "serialize", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, PartialEq)]
pub struct SpanContext {
trace_id: u128,
span_id: u64,
trace_id: TraceId,
span_id: SpanId,
trace_flags: u8,
is_remote: bool,
}

impl SpanContext {
/// Create an invalid empty span context
pub fn empty_context() -> Self {
SpanContext::new(0, 0, 0, false)
SpanContext::new(TraceId::invalid(), SpanId::invalid(), 0, false)
}

/// Construct a new `SpanContext`
pub fn new(trace_id: u128, span_id: u64, trace_flags: u8, is_remote: bool) -> Self {
pub fn new(trace_id: TraceId, span_id: SpanId, trace_flags: u8, is_remote: bool) -> Self {
SpanContext {
trace_id,
span_id,
Expand All @@ -49,12 +95,12 @@ impl SpanContext {
}

/// A valid trace identifier is a non-zero `u128`.
pub fn trace_id(&self) -> u128 {
pub fn trace_id(&self) -> TraceId {
self.trace_id
}

/// A valid span identifier is a non-zero `u64`.
pub fn span_id(&self) -> u64 {
pub fn span_id(&self) -> SpanId {
self.span_id
}

Expand All @@ -67,7 +113,7 @@ impl SpanContext {
/// Returns a bool flag which is true if the `SpanContext` has a valid (non-zero) `trace_id`
/// and a valid (non-zero) `span_id`.
pub fn is_valid(&self) -> bool {
self.trace_id != 0 && self.span_id != 0
self.trace_id.0 != 0 && self.span_id.0 != 0
}

/// Returns true if the `SpanContext` was propagated from a remote parent.
Expand Down
Loading

0 comments on commit b31b674

Please sign in to comment.