Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions opentelemetry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,9 @@ mod context;

pub use context::{Context, ContextGuard};

mod trace_context;
pub use trace_context::{SpanId, TraceFlags, TraceId};

mod common;

#[cfg(any(feature = "testing", test))]
Expand Down
4 changes: 1 addition & 3 deletions opentelemetry/src/logs/record.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::{Key, StringValue};

#[cfg(feature = "trace")]
use crate::trace::{SpanId, TraceFlags, TraceId};
use crate::{SpanId, TraceFlags, TraceId};

use std::{borrow::Cow, collections::HashMap, time::SystemTime};

Expand Down Expand Up @@ -47,7 +46,6 @@ pub trait LogRecord {
V: Into<AnyValue>;

/// Sets the trace context of the log.
#[cfg(feature = "trace")]
fn set_trace_context(
&mut self,
trace_id: TraceId,
Expand Down
4 changes: 2 additions & 2 deletions opentelemetry/src/testing/trace.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
trace::{Span, SpanContext, SpanId, Status, TraceId},
KeyValue,
trace::{Span, SpanContext, Status},
KeyValue, SpanId, TraceId,
};
use std::borrow::Cow;

Expand Down
3 changes: 2 additions & 1 deletion opentelemetry/src/trace/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,12 @@ pub use self::{
get_active_span, mark_span_as_active, FutureExt, SpanRef, TraceContextExt, WithContext,
},
span::{Span, SpanKind, Status},
span_context::{SpanContext, SpanId, TraceFlags, TraceId, TraceState},
span_context::{SpanContext, TraceState},
tracer::{SamplingDecision, SamplingResult, SpanBuilder, Tracer},
tracer_provider::TracerProvider,
};
use crate::KeyValue;
pub use crate::{SpanId, TraceFlags, TraceId};
use std::sync::PoisonError;

// TODO - Move ExportError and TraceError to opentelemetry-sdk
Expand Down
252 changes: 1 addition & 251 deletions opentelemetry/src/trace/span_context.rs
Original file line number Diff line number Diff line change
@@ -1,218 +1,10 @@
use crate::trace::{TraceError, TraceResult};
use crate::{SpanId, TraceFlags, TraceId};
use std::collections::VecDeque;
use std::fmt;
use std::hash::Hash;
use std::num::ParseIntError;
use std::ops::{BitAnd, BitOr, Not};
use std::str::FromStr;
use thiserror::Error;

/// Flags that can be set on a [`SpanContext`].
///
/// The current version of the specification only supports a single flag
/// [`TraceFlags::SAMPLED`].
///
/// See the W3C TraceContext specification's [trace-flags] section for more
/// details.
///
/// [trace-flags]: https://www.w3.org/TR/trace-context/#trace-flags
#[derive(Clone, Debug, Default, PartialEq, Eq, Copy, Hash)]
pub struct TraceFlags(u8);

impl TraceFlags {
/// Trace flags with the `sampled` flag set to `0`.
///
/// Spans that are not sampled will be ignored by most tracing tools.
/// See the `sampled` section of the [W3C TraceContext specification] for details.
///
/// [W3C TraceContext specification]: https://www.w3.org/TR/trace-context/#sampled-flag
pub const NOT_SAMPLED: TraceFlags = TraceFlags(0x00);

/// Trace flags with the `sampled` flag set to `1`.
///
/// Spans that are not sampled will be ignored by most tracing tools.
/// See the `sampled` section of the [W3C TraceContext specification] for details.
///
/// [W3C TraceContext specification]: https://www.w3.org/TR/trace-context/#sampled-flag
pub const SAMPLED: TraceFlags = TraceFlags(0x01);

/// Construct new trace flags
pub const fn new(flags: u8) -> Self {
TraceFlags(flags)
}

/// Returns `true` if the `sampled` flag is set
pub fn is_sampled(&self) -> bool {
(*self & TraceFlags::SAMPLED) == TraceFlags::SAMPLED
}

/// Returns copy of the current flags with the `sampled` flag set.
pub fn with_sampled(&self, sampled: bool) -> Self {
if sampled {
*self | TraceFlags::SAMPLED
} else {
*self & !TraceFlags::SAMPLED
}
}

/// Returns the flags as a `u8`
pub fn to_u8(self) -> u8 {
self.0
}
}

impl BitAnd for TraceFlags {
type Output = Self;

fn bitand(self, rhs: Self) -> Self::Output {
Self(self.0 & rhs.0)
}
}

impl BitOr for TraceFlags {
type Output = Self;

fn bitor(self, rhs: Self) -> Self::Output {
Self(self.0 | rhs.0)
}
}

impl Not for TraceFlags {
type Output = Self;

fn not(self) -> Self::Output {
Self(!self.0)
}
}

impl fmt::LowerHex for TraceFlags {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::LowerHex::fmt(&self.0, f)
}
}

/// A 16-byte value which identifies a given trace.
///
/// The id is valid if it contains at least one non-zero byte.
#[derive(Clone, PartialEq, Eq, Copy, Hash)]
pub struct TraceId(u128);

impl TraceId {
/// Invalid trace id
pub const INVALID: TraceId = TraceId(0);

/// Create a trace id from its representation as a byte array.
pub const fn from_bytes(bytes: [u8; 16]) -> Self {
TraceId(u128::from_be_bytes(bytes))
}

/// Return the representation of this trace id as a byte array.
pub const fn to_bytes(self) -> [u8; 16] {
self.0.to_be_bytes()
}

/// Converts a string in base 16 to a trace id.
///
/// # Examples
///
/// ```
/// use opentelemetry::trace::TraceId;
///
/// assert!(TraceId::from_hex("42").is_ok());
/// assert!(TraceId::from_hex("58406520a006649127e371903a2de979").is_ok());
///
/// assert!(TraceId::from_hex("not_hex").is_err());
/// ```
pub fn from_hex(hex: &str) -> Result<Self, ParseIntError> {
u128::from_str_radix(hex, 16).map(TraceId)
}
}

impl From<u128> for TraceId {
fn from(value: u128) -> Self {
TraceId(value)
}
}

impl fmt::Debug for TraceId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_fmt(format_args!("{:032x}", self.0))
}
}

impl fmt::Display for TraceId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_fmt(format_args!("{:032x}", self.0))
}
}

impl fmt::LowerHex for TraceId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::LowerHex::fmt(&self.0, f)
}
}

/// An 8-byte value which identifies a given span.
///
/// The id is valid if it contains at least one non-zero byte.
#[derive(Clone, PartialEq, Eq, Copy, Hash)]
pub struct SpanId(u64);

impl SpanId {
/// Invalid span id
pub const INVALID: SpanId = SpanId(0);

/// Create a span id from its representation as a byte array.
pub const fn from_bytes(bytes: [u8; 8]) -> Self {
SpanId(u64::from_be_bytes(bytes))
}

/// Return the representation of this span id as a byte array.
pub const fn to_bytes(self) -> [u8; 8] {
self.0.to_be_bytes()
}

/// Converts a string in base 16 to a span id.
///
/// # Examples
///
/// ```
/// use opentelemetry::trace::SpanId;
///
/// assert!(SpanId::from_hex("42").is_ok());
/// assert!(SpanId::from_hex("58406520a0066491").is_ok());
///
/// assert!(SpanId::from_hex("not_hex").is_err());
/// ```
pub fn from_hex(hex: &str) -> Result<Self, ParseIntError> {
u64::from_str_radix(hex, 16).map(SpanId)
}
}

impl From<u64> for SpanId {
fn from(value: u64) -> Self {
SpanId(value)
}
}

impl fmt::Debug for SpanId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_fmt(format_args!("{:016x}", self.0))
}
}

impl fmt::Display for SpanId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_fmt(format_args!("{:016x}", self.0))
}
}

impl fmt::LowerHex for SpanId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::LowerHex::fmt(&self.0, f)
}
}

/// TraceState carries system-specific configuration data, represented as a list
/// of key-value pairs. TraceState allows multiple tracing systems to
/// participate in the same trace.
Expand Down Expand Up @@ -546,24 +338,6 @@ mod tests {
use super::*;
use crate::{trace::TraceContextExt, Context};

#[rustfmt::skip]
fn trace_id_test_data() -> Vec<(TraceId, &'static str, [u8; 16])> {
vec![
(TraceId(0), "00000000000000000000000000000000", [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
(TraceId(42), "0000000000000000000000000000002a", [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42]),
(TraceId(126642714606581564793456114182061442190), "5f467fe7bf42676c05e20ba4a90e448e", [95, 70, 127, 231, 191, 66, 103, 108, 5, 226, 11, 164, 169, 14, 68, 142])
]
}

#[rustfmt::skip]
fn span_id_test_data() -> Vec<(SpanId, &'static str, [u8; 8])> {
vec![
(SpanId(0), "0000000000000000", [0, 0, 0, 0, 0, 0, 0, 0]),
(SpanId(42), "000000000000002a", [0, 0, 0, 0, 0, 0, 0, 42]),
(SpanId(5508496025762705295), "4c721bf33e3caf8f", [76, 114, 27, 243, 62, 60, 175, 143])
]
}

#[rustfmt::skip]
fn trace_state_test_data() -> Vec<(TraceState, &'static str, &'static str)> {
vec![
Expand All @@ -573,30 +347,6 @@ mod tests {
]
}

#[test]
fn test_trace_id() {
for test_case in trace_id_test_data() {
assert_eq!(format!("{}", test_case.0), test_case.1);
assert_eq!(format!("{:032x}", test_case.0), test_case.1);
assert_eq!(test_case.0.to_bytes(), test_case.2);

assert_eq!(test_case.0, TraceId::from_hex(test_case.1).unwrap());
assert_eq!(test_case.0, TraceId::from_bytes(test_case.2));
}
}

#[test]
fn test_span_id() {
for test_case in span_id_test_data() {
assert_eq!(format!("{}", test_case.0), test_case.1);
assert_eq!(format!("{:016x}", test_case.0), test_case.1);
assert_eq!(test_case.0.to_bytes(), test_case.2);

assert_eq!(test_case.0, SpanId::from_hex(test_case.1).unwrap());
assert_eq!(test_case.0, SpanId::from_bytes(test_case.2));
}
}

#[test]
fn test_trace_state() {
for test_case in trace_state_test_data() {
Expand Down
4 changes: 2 additions & 2 deletions opentelemetry/src/trace/tracer.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
trace::{Event, Link, Span, SpanId, SpanKind, Status, TraceContextExt, TraceId, TraceState},
Context, KeyValue,
trace::{Event, Link, Span, SpanKind, Status, TraceContextExt, TraceState},
Context, KeyValue, SpanId, TraceId,
};
use std::borrow::Cow;
use std::time::SystemTime;
Expand Down
Loading