/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 | | } |