use crate::{
propagation::{text_map_propagator::FieldIter, Extractor, Injector, TextMapPropagator},
trace::{self, TraceContextExt, TraceFlags, TraceState},
Context, InstrumentationLibrary, KeyValue,
};
use std::{borrow::Cow, sync::Arc, time::SystemTime};
#[derive(Clone, Debug, Default)]
pub struct NoopTracerProvider {
_private: (),
}
impl NoopTracerProvider {
pub fn new() -> Self {
NoopTracerProvider { _private: () }
}
}
impl trace::TracerProvider for NoopTracerProvider {
type Tracer = NoopTracer;
fn library_tracer(&self, _library: Arc<InstrumentationLibrary>) -> Self::Tracer {
NoopTracer::new()
}
}
#[derive(Clone, Debug)]
pub struct NoopSpan {
span_context: trace::SpanContext,
}
impl Default for NoopSpan {
fn default() -> Self {
NoopSpan::new()
}
}
impl NoopSpan {
pub fn new() -> Self {
NoopSpan {
span_context: trace::SpanContext::new(
trace::TraceId::INVALID,
trace::SpanId::INVALID,
TraceFlags::default(),
false,
TraceState::default(),
),
}
}
}
impl trace::Span for NoopSpan {
fn add_event<T>(&mut self, _name: T, _attributes: Vec<KeyValue>)
where
T: Into<Cow<'static, str>>,
{
}
fn add_event_with_timestamp<T>(
&mut self,
_name: T,
_timestamp: SystemTime,
_attributes: Vec<KeyValue>,
) where
T: Into<Cow<'static, str>>,
{
}
fn span_context(&self) -> &trace::SpanContext {
&self.span_context
}
fn is_recording(&self) -> bool {
false
}
fn set_attribute(&mut self, _attribute: KeyValue) {
}
fn set_status(&mut self, _status: trace::Status) {
}
fn update_name<T>(&mut self, _new_name: T)
where
T: Into<Cow<'static, str>>,
{
}
fn end_with_timestamp(&mut self, _timestamp: SystemTime) {
}
}
#[derive(Clone, Debug, Default)]
pub struct NoopTracer {
_private: (),
}
impl NoopTracer {
pub fn new() -> Self {
NoopTracer { _private: () }
}
}
impl trace::Tracer for NoopTracer {
type Span = NoopSpan;
fn build_with_context(&self, _builder: trace::SpanBuilder, parent_cx: &Context) -> Self::Span {
if parent_cx.has_active_span() {
NoopSpan {
span_context: parent_cx.span().span_context().clone(),
}
} else {
NoopSpan::new()
}
}
}
#[derive(Debug, Default)]
pub struct NoopTextMapPropagator {
_private: (),
}
impl NoopTextMapPropagator {
pub fn new() -> Self {
NoopTextMapPropagator { _private: () }
}
}
impl TextMapPropagator for NoopTextMapPropagator {
fn inject_context(&self, _cx: &Context, _injector: &mut dyn Injector) {
}
fn extract_with_context(&self, _cx: &Context, _extractor: &dyn Extractor) -> Context {
Context::current()
}
fn fields(&self) -> FieldIter<'_> {
FieldIter::new(&[])
}
}
#[cfg(all(test, feature = "testing", feature = "trace"))]
mod tests {
use super::*;
use crate::testing::trace::TestSpan;
use crate::trace::{self, Span, Tracer};
fn valid_span_context() -> trace::SpanContext {
trace::SpanContext::new(
trace::TraceId::from_u128(42),
trace::SpanId::from_u64(42),
trace::TraceFlags::default(),
true,
TraceState::default(),
)
}
#[test]
fn noop_tracer_defaults_to_invalid_span() {
let tracer = NoopTracer::new();
let span = tracer.start_with_context("foo", &Context::new());
assert!(!span.span_context().is_valid());
}
#[test]
fn noop_tracer_propagates_valid_span_context_from_builder() {
let tracer = NoopTracer::new();
let builder = tracer.span_builder("foo");
let span = tracer.build_with_context(
builder,
&Context::new().with_span(TestSpan(valid_span_context())),
);
assert!(span.span_context().is_valid());
}
#[test]
fn noop_tracer_propagates_valid_span_context_from_explicitly_specified_context() {
let tracer = NoopTracer::new();
let cx = Context::new().with_span(NoopSpan {
span_context: valid_span_context(),
});
let span = tracer.start_with_context("foo", &cx);
assert!(span.span_context().is_valid());
}
#[test]
fn noop_tracer_propagates_valid_span_context_from_remote_span_context() {
let tracer = NoopTracer::new();
let cx = Context::new().with_remote_span_context(valid_span_context());
let span = tracer.start_with_context("foo", &cx);
assert!(span.span_context().is_valid());
}
}