Coverage Report

Created: 2024-12-17 06:15

/src/linkerd2-proxy/linkerd/trace-context/src/lib.rs
Line
Count
Source (jump to first uncovered line)
1
#![deny(rust_2018_idioms, clippy::disallowed_methods, clippy::disallowed_types)]
2
#![forbid(unsafe_code)]
3
4
pub mod export;
5
mod propagation;
6
mod service;
7
8
pub use self::service::TraceContext;
9
use bytes::Bytes;
10
use linkerd_error::Error;
11
use rand::Rng;
12
use std::collections::HashMap;
13
use std::fmt;
14
use std::time::SystemTime;
15
use thiserror::Error;
16
17
const SPAN_ID_LEN: usize = 8;
18
19
#[derive(Debug, Default)]
20
pub struct Id(Vec<u8>);
21
22
#[derive(Debug, Error)]
23
#[error("ID '{:?} should have {} bytes, but it has {}", self.id, self.expected_size, self.actual_size)]
24
pub struct IdLengthError {
25
    id: Vec<u8>,
26
    expected_size: usize,
27
    actual_size: usize,
28
}
29
30
impl Id {
31
0
    pub fn into_bytes<const N: usize>(self) -> Result<[u8; N], IdLengthError> {
32
0
        self.as_ref().try_into().map_err(|_| {
33
0
            let bytes: Vec<u8> = self.into();
34
0
            IdLengthError {
35
0
                expected_size: N,
36
0
                actual_size: bytes.len(),
37
0
                id: bytes,
38
0
            }
39
0
        })
40
0
    }
41
}
42
43
#[derive(Debug, Default)]
44
pub struct Flags(u8);
45
46
#[derive(Debug, Error)]
47
#[error("insufficient bytes when decoding binary header")]
48
pub struct InsufficientBytes;
49
50
#[derive(Debug)]
51
pub struct Span {
52
    pub trace_id: Id,
53
    pub span_id: Id,
54
    pub parent_id: Id,
55
    pub span_name: String,
56
    pub start: SystemTime,
57
    pub end: SystemTime,
58
    pub labels: HashMap<&'static str, String>,
59
}
60
61
pub trait SpanSink {
62
    fn is_enabled(&self) -> bool;
63
64
    fn try_send(&mut self, span: Span) -> Result<(), Error>;
65
}
66
67
impl<K: SpanSink> SpanSink for Option<K> {
68
    #[inline]
69
1.07M
    fn is_enabled(&self) -> bool {
70
1.07M
        self.as_ref().map(SpanSink::is_enabled).unwrap_or(false)
71
1.07M
    }
<core::option::Option<linkerd_app_core::http_tracing::SpanConverter> as linkerd_trace_context::SpanSink>::is_enabled
Line
Count
Source
69
1.07M
    fn is_enabled(&self) -> bool {
70
1.07M
        self.as_ref().map(SpanSink::is_enabled).unwrap_or(false)
71
1.07M
    }
Unexecuted instantiation: <core::option::Option<_> as linkerd_trace_context::SpanSink>::is_enabled
72
73
    #[inline]
74
0
    fn try_send(&mut self, span: Span) -> Result<(), Error> {
75
0
        self.as_mut().expect("Must be enabled").try_send(span)
76
0
    }
Unexecuted instantiation: <core::option::Option<linkerd_app_core::http_tracing::SpanConverter> as linkerd_trace_context::SpanSink>::try_send
Unexecuted instantiation: <core::option::Option<_> as linkerd_trace_context::SpanSink>::try_send
77
}
78
79
// === impl Id ===
80
81
impl Id {
82
0
    fn new_span_id<R: Rng>(rng: &mut R) -> Self {
83
0
        let mut bytes = vec![0; SPAN_ID_LEN];
84
0
        rng.fill(bytes.as_mut_slice());
85
0
        Self(bytes)
86
0
    }
Unexecuted instantiation: <linkerd_trace_context::Id>::new_span_id::<rand::rngs::thread::ThreadRng>
Unexecuted instantiation: <linkerd_trace_context::Id>::new_span_id::<_>
87
}
88
89
impl From<Id> for Vec<u8> {
90
    fn from(Id(bytes): Id) -> Vec<u8> {
91
        bytes
92
    }
93
}
94
95
impl AsRef<[u8]> for Id {
96
0
    fn as_ref(&self) -> &[u8] {
97
0
        self.0.as_ref()
98
0
    }
99
}
100
101
impl fmt::Display for Id {
102
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103
0
        for b in self.0.iter() {
104
0
            write!(f, "{:02x?}", b)?;
105
        }
106
0
        Ok(())
107
0
    }
108
}
109
110
impl From<Bytes> for Id {
111
0
    fn from(buf: Bytes) -> Self {
112
0
        Id(buf.to_vec())
113
0
    }
114
}
115
116
// === impl Flags ===
117
118
impl Flags {
119
0
    pub fn is_sampled(&self) -> bool {
120
0
        self.0 & 1 == 1
121
0
    }
122
}
123
124
impl fmt::Display for Flags {
125
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126
0
        write!(f, "{:02x?}", self.0)
127
0
    }
128
}
129
130
impl TryFrom<Bytes> for Flags {
131
    type Error = InsufficientBytes;
132
133
0
    fn try_from(buf: Bytes) -> Result<Self, Self::Error> {
134
0
        buf.first().map(|b| Flags(*b)).ok_or(InsufficientBytes)
135
0
    }
136
}