libdd_trace_stats/span_concentrator/
stat_span.rs1use libdd_trace_protobuf::pb;
8use libdd_trace_utils::span::v1::{AttributeValue, Span as SpanV1, SpanKind, TraceChunk};
9use libdd_trace_utils::span::{trace_utils, trace_utils_v1, v04::Span, TraceData};
13use libdd_trace_utils::trace_utils as trace_utils_pb;
14use std::borrow::Borrow;
15
16pub trait StatSpan<'a> {
18 fn service(&'a self) -> &'a str;
20 fn resource(&'a self) -> &'a str;
22 fn name(&'a self) -> &'a str;
24 fn r#type(&'a self) -> &'a str;
26 fn start(&'a self) -> i64;
28 fn duration(&'a self) -> i64;
30 fn is_error(&'a self) -> bool;
32 fn is_trace_root(&'a self) -> bool;
34 fn is_measured(&'a self) -> bool;
36 fn is_partial_snapshot(&'a self) -> bool;
38 fn has_top_level(&'a self) -> bool;
40 fn get_meta(&'a self, key: &str) -> Option<&'a str>;
42 fn get_metrics(&'a self, key: &str) -> Option<f64>;
44}
45
46impl<'a, T: TraceData> StatSpan<'a> for Span<T> {
47 fn service(&'a self) -> &'a str {
48 self.service.borrow()
49 }
50
51 fn resource(&'a self) -> &'a str {
52 self.resource.borrow()
53 }
54
55 fn name(&'a self) -> &'a str {
56 self.name.borrow()
57 }
58
59 fn r#type(&'a self) -> &'a str {
60 self.r#type.borrow()
61 }
62
63 fn start(&'a self) -> i64 {
64 self.start
65 }
66
67 fn duration(&'a self) -> i64 {
68 self.duration
69 }
70
71 fn is_error(&'a self) -> bool {
72 self.error != 0
73 }
74
75 fn is_trace_root(&'a self) -> bool {
76 self.parent_id == 0
77 }
78
79 fn is_measured(&'a self) -> bool {
80 trace_utils::is_measured(self)
81 }
82
83 fn is_partial_snapshot(&'a self) -> bool {
84 trace_utils::is_partial_snapshot(self)
85 }
86
87 fn has_top_level(&'a self) -> bool {
88 trace_utils::has_top_level(self)
89 }
90
91 fn get_meta(&'a self, key: &str) -> Option<&'a str> {
92 self.meta.get(key).map(|v| v.borrow())
93 }
94
95 fn get_metrics(&'a self, key: &str) -> Option<f64> {
96 self.metrics.get(key).copied()
97 }
98}
99
100impl<'a, T: TraceData> StatSpan<'a> for SpanV1<T> {
101 fn service(&'a self) -> &'a str {
102 self.service.borrow()
103 }
104
105 fn resource(&'a self) -> &'a str {
106 self.resource.borrow()
107 }
108
109 fn name(&'a self) -> &'a str {
110 self.name.borrow()
111 }
112
113 fn r#type(&'a self) -> &'a str {
114 self.r#type.borrow()
115 }
116
117 fn start(&'a self) -> i64 {
118 self.start
119 }
120
121 fn duration(&'a self) -> i64 {
122 self.duration
123 }
124
125 fn is_error(&'a self) -> bool {
126 self.error
127 }
128
129 fn is_trace_root(&'a self) -> bool {
130 self.parent_id == 0
131 }
132
133 fn is_measured(&'a self) -> bool {
134 trace_utils_v1::is_measured(self)
135 }
136
137 fn is_partial_snapshot(&'a self) -> bool {
138 trace_utils_v1::is_partial_snapshot(self)
139 }
140
141 fn has_top_level(&'a self) -> bool {
142 trace_utils_v1::has_top_level(self)
143 }
144
145 fn get_meta(&'a self, key: &str) -> Option<&'a str> {
146 match self.attributes.get(key) {
147 Some(AttributeValue::String(s)) => Some(s.borrow()),
148 _ if key == "span.kind" && self.span_kind != SpanKind::Internal => {
153 Some(self.span_kind.as_meta_str())
154 }
155 _ => None,
156 }
157 }
158
159 fn get_metrics(&'a self, key: &str) -> Option<f64> {
160 match self.attributes.get(key) {
161 Some(AttributeValue::Float(v)) => Some(*v),
162 Some(AttributeValue::Int(v)) => Some(*v as f64),
163 _ => None,
164 }
165 }
166}
167
168pub struct ChunkSpanView<'a, T: TraceData> {
175 pub span: &'a SpanV1<T>,
176 pub chunk: &'a TraceChunk<T>,
177}
178
179impl<'a, T: TraceData> StatSpan<'a> for ChunkSpanView<'a, T> {
180 fn service(&'a self) -> &'a str {
181 self.span.service()
182 }
183
184 fn resource(&'a self) -> &'a str {
185 self.span.resource()
186 }
187
188 fn name(&'a self) -> &'a str {
189 self.span.name()
190 }
191
192 fn r#type(&'a self) -> &'a str {
193 self.span.r#type()
194 }
195
196 fn start(&'a self) -> i64 {
197 self.span.start()
198 }
199
200 fn duration(&'a self) -> i64 {
201 self.span.duration()
202 }
203
204 fn is_error(&'a self) -> bool {
205 self.span.is_error()
206 }
207
208 fn is_trace_root(&'a self) -> bool {
209 self.span.is_trace_root()
210 }
211
212 fn is_measured(&'a self) -> bool {
213 self.span.is_measured()
214 }
215
216 fn is_partial_snapshot(&'a self) -> bool {
217 self.span.is_partial_snapshot()
218 }
219
220 fn has_top_level(&'a self) -> bool {
221 self.span.has_top_level()
222 }
223
224 fn get_meta(&'a self, key: &str) -> Option<&'a str> {
225 self.span.get_meta(key).or_else(|| {
226 if key == "_dd.origin" {
229 let origin = self.chunk.origin.borrow();
230 if !origin.is_empty() {
231 return Some(origin);
232 }
233 }
234 match self.chunk.attributes.get(key) {
235 Some(AttributeValue::String(s)) => Some(s.borrow()),
236 _ => None,
237 }
238 })
239 }
240
241 fn get_metrics(&'a self, key: &str) -> Option<f64> {
242 self.span
243 .get_metrics(key)
244 .or_else(|| match self.chunk.attributes.get(key) {
245 Some(AttributeValue::Float(v)) => Some(*v),
246 Some(AttributeValue::Int(v)) => Some(*v as f64),
247 _ => None,
248 })
249 }
250}
251
252impl<'a> StatSpan<'a> for pb::Span {
253 fn service(&'a self) -> &'a str {
254 self.service.as_str()
255 }
256
257 fn resource(&'a self) -> &'a str {
258 self.resource.as_str()
259 }
260
261 fn name(&'a self) -> &'a str {
262 self.name.as_str()
263 }
264
265 fn r#type(&'a self) -> &'a str {
266 self.r#type.as_str()
267 }
268
269 fn start(&'a self) -> i64 {
270 self.start
271 }
272
273 fn duration(&'a self) -> i64 {
274 self.duration
275 }
276
277 fn is_error(&'a self) -> bool {
278 self.error != 0
279 }
280
281 fn is_trace_root(&'a self) -> bool {
282 self.parent_id == 0
283 }
284
285 fn is_measured(&'a self) -> bool {
286 trace_utils_pb::is_measured(self)
287 }
288
289 fn is_partial_snapshot(&'a self) -> bool {
290 trace_utils_pb::is_partial_snapshot(self)
291 }
292
293 fn has_top_level(&'a self) -> bool {
294 trace_utils_pb::has_top_level(self)
295 }
296
297 fn get_meta(&'a self, key: &str) -> Option<&'a str> {
298 self.meta.get(key).map(|v| v.as_str())
299 }
300
301 fn get_metrics(&'a self, key: &str) -> Option<f64> {
302 self.metrics.get(key).copied()
303 }
304}