tracing_distributed/
telemetry.rs

1use crate::trace::{Event, Span};
2use std::marker::PhantomData;
3
4/// Represents the ability to publish events and spans to some arbitrary backend.
5pub trait Telemetry {
6    /// Type used to record tracing fields.
7    type Visitor: tracing::field::Visit;
8    /// Globally unique identifier, uniquely identifies a trace.
9    type TraceId: Send + Sync + Clone;
10    /// Identifies spans within a trace.
11    type SpanId: Send + Sync + Clone;
12
13    /// Initialize a visitor, used to record values from spans and events as they are observed
14    fn mk_visitor(&self) -> Self::Visitor;
15
16    /// Report a `Span` to this Telemetry instance's backend.
17    fn report_span(&self, span: Span<Self::Visitor, Self::SpanId, Self::TraceId>);
18
19    /// Report an `Event` to this Telemetry instance's backend.
20    fn report_event(&self, event: Event<Self::Visitor, Self::SpanId, Self::TraceId>);
21}
22
23/// Visitor that records no information when visiting tracing fields.
24#[derive(Default, Debug)]
25pub struct BlackholeVisitor;
26
27impl tracing::field::Visit for BlackholeVisitor {
28    fn record_debug(&mut self, _: &tracing::field::Field, _: &dyn std::fmt::Debug) {}
29}
30
31/// Telemetry implementation that does not publish information to any backend.
32/// For use in tests.
33pub struct BlackholeTelemetry<S, T>(PhantomData<S>, PhantomData<T>);
34
35impl<S, T> Default for BlackholeTelemetry<S, T> {
36    fn default() -> Self {
37        BlackholeTelemetry(PhantomData, PhantomData)
38    }
39}
40
41impl<SpanId, TraceId> Telemetry for BlackholeTelemetry<SpanId, TraceId>
42where
43    SpanId: 'static + Clone + Send + Sync,
44    TraceId: 'static + Clone + Send + Sync,
45{
46    type Visitor = BlackholeVisitor;
47    type TraceId = TraceId;
48    type SpanId = SpanId;
49
50    fn mk_visitor(&self) -> Self::Visitor {
51        Default::default()
52    }
53
54    fn report_span(&self, _: Span<Self::Visitor, Self::SpanId, Self::TraceId>) {}
55
56    fn report_event(&self, _: Event<Self::Visitor, Self::SpanId, Self::TraceId>) {}
57}
58
59#[cfg(test)]
60pub(crate) mod test {
61    use super::*;
62    use std::sync::Arc;
63    use std::sync::Mutex;
64
65    // simplified ID types
66    pub(crate) type TraceId = u64;
67    pub(crate) type SpanId = tracing::Id;
68
69    /// Mock telemetry capability
70    pub struct TestTelemetry {
71        spans: Arc<Mutex<Vec<Span<BlackholeVisitor, SpanId, TraceId>>>>,
72        events: Arc<Mutex<Vec<Event<BlackholeVisitor, SpanId, TraceId>>>>,
73    }
74
75    impl TestTelemetry {
76        pub fn new(
77            spans: Arc<Mutex<Vec<Span<BlackholeVisitor, SpanId, TraceId>>>>,
78            events: Arc<Mutex<Vec<Event<BlackholeVisitor, SpanId, TraceId>>>>,
79        ) -> Self {
80            TestTelemetry { spans, events }
81        }
82    }
83
84    impl Telemetry for TestTelemetry {
85        type Visitor = BlackholeVisitor;
86        type SpanId = SpanId;
87        type TraceId = TraceId;
88
89        fn mk_visitor(&self) -> Self::Visitor {
90            BlackholeVisitor
91        }
92
93        fn report_span(&self, span: Span<BlackholeVisitor, SpanId, TraceId>) {
94            // succeed or die. failure is unrecoverable (mutex poisoned)
95            let mut spans = self.spans.lock().unwrap();
96            spans.push(span);
97        }
98
99        fn report_event(&self, event: Event<BlackholeVisitor, SpanId, TraceId>) {
100            // succeed or die. failure is unrecoverable (mutex poisoned)
101            let mut events = self.events.lock().unwrap();
102            events.push(event);
103        }
104    }
105}