Skip to main content

saluki_core/data_model/event/trace/
mod.rs

1//! Traces.
2
3use saluki_common::collections::FastHashMap;
4use saluki_context::tags::SharedTagSet;
5use stringtheory::MetaString;
6
7/// Trace-level sampling metadata.
8///
9/// This struct stores sampling-related metadata that applies to the entire trace,
10/// typically set by the trace sampler and consumed by the encoder.
11#[derive(Clone, Debug, PartialEq)]
12pub struct TraceSampling {
13    /// Whether or not the trace was dropped during sampling.
14    pub dropped_trace: bool,
15    /// The sampling priority assigned to this trace.
16    ///
17    /// Common values include:
18    /// - `2`: Manual keep (user-requested)
19    /// - `1`: Auto keep (sampled in)
20    /// - `0`: Auto drop (sampled out)
21    /// - `-1`: Manual drop (user-requested drop)
22    pub priority: Option<i32>,
23
24    /// The decision maker identifier indicating which sampler made the sampling decision.
25    ///
26    /// Common values include:
27    /// - `-9`: Probabilistic sampler
28    /// - `-4`: Errors sampler
29    /// - `None`: No decision maker set
30    pub decision_maker: Option<MetaString>,
31
32    /// The OTLP sampling rate applied to this trace, formatted as a string (e.g., "0.25").
33    ///
34    /// This corresponds to the `_dd.otlp_sr` tag and represents the effective sampling rate
35    /// from the OTLP ingest path.
36    pub otlp_sampling_rate: Option<MetaString>,
37}
38
39impl TraceSampling {
40    /// Creates a new `TraceSampling` instance.
41    pub fn new(
42        dropped_trace: bool, priority: Option<i32>, decision_maker: Option<MetaString>,
43        otlp_sampling_rate: Option<MetaString>,
44    ) -> Self {
45        Self {
46            dropped_trace,
47            priority,
48            decision_maker,
49            otlp_sampling_rate,
50        }
51    }
52}
53
54/// A trace event.
55///
56/// A trace is a collection of spans that represent a distributed trace.
57#[derive(Clone, Debug, PartialEq)]
58pub struct Trace {
59    /// The spans that make up this trace.
60    spans: Vec<Span>,
61    /// Resource-level tags associated with this trace.
62    ///
63    /// This is derived from the resource of the spans and used to construct the tracer payload.
64    resource_tags: SharedTagSet,
65    /// Trace-level sampling metadata.
66    ///
67    /// This field contains sampling decision information (priority, decision maker, rates)
68    /// that applies to the entire trace. It is set by the trace sampler component and consumed
69    /// by the encoder to populate trace chunk metadata.
70    sampling: Option<TraceSampling>,
71}
72
73impl Trace {
74    /// Creates a new `Trace` with the given spans.
75    pub fn new(spans: Vec<Span>, resource_tags: impl Into<SharedTagSet>) -> Self {
76        Self {
77            spans,
78            resource_tags: resource_tags.into(),
79            sampling: None,
80        }
81    }
82
83    /// Returns a reference to the spans in this trace.
84    pub fn spans(&self) -> &[Span] {
85        &self.spans
86    }
87
88    /// Returns a mutable reference to the spans in this trace.
89    pub fn spans_mut(&mut self) -> &mut [Span] {
90        &mut self.spans
91    }
92
93    /// Replaces the spans in this trace with the given spans.
94    pub fn set_spans(&mut self, spans: Vec<Span>) {
95        self.spans = spans;
96    }
97
98    /// Retains only the spans specified by the predicate.
99    ///
100    /// Returns the number of spans retained. If no spans match, the trace is left unchanged.
101    pub fn retain_spans<F>(&mut self, mut f: F) -> usize
102    where
103        F: FnMut(&Span) -> bool,
104    {
105        if self.spans.is_empty() {
106            return 0;
107        }
108
109        let mut has_match = false;
110        for span in self.spans.iter() {
111            if f(span) {
112                has_match = true;
113                break;
114            }
115        }
116
117        if !has_match {
118            return 0;
119        }
120
121        self.spans.retain(|span| f(span));
122        self.spans.shrink_to_fit();
123        self.spans.len()
124    }
125
126    /// Returns the resource-level tags associated with this trace.
127    pub fn resource_tags(&self) -> &SharedTagSet {
128        &self.resource_tags
129    }
130
131    /// Returns a reference to the trace-level sampling metadata, if present.
132    pub fn sampling(&self) -> Option<&TraceSampling> {
133        self.sampling.as_ref()
134    }
135
136    /// Sets the trace-level sampling metadata.
137    pub fn set_sampling(&mut self, sampling: Option<TraceSampling>) {
138        self.sampling = sampling;
139    }
140}
141
142/// A span event.
143#[derive(Clone, Debug, PartialEq, Default)]
144pub struct Span {
145    /// The name of the service associated with this span.
146    service: MetaString,
147    /// The operation name of this span.
148    name: MetaString,
149    /// The resource associated with this span.
150    resource: MetaString,
151    /// The trace identifier this span belongs to.
152    trace_id: u64,
153    /// The unique identifier of this span.
154    span_id: u64,
155    /// The identifier of this span's parent, if any.
156    parent_id: u64,
157    /// The start timestamp of this span in nanoseconds since Unix epoch.
158    start: u64,
159    /// The duration of this span in nanoseconds.
160    duration: u64,
161    /// Error flag represented as 0 (no error) or 1 (error).
162    error: i32,
163    /// String-valued tags attached to this span.
164    meta: FastHashMap<MetaString, MetaString>,
165    /// Numeric-valued tags attached to this span.
166    metrics: FastHashMap<MetaString, f64>,
167    /// Span type classification (e.g., web, db, lambda).
168    span_type: MetaString,
169    /// Structured metadata payloads.
170    meta_struct: FastHashMap<MetaString, Vec<u8>>,
171    /// Links describing relationships to other spans.
172    span_links: Vec<SpanLink>,
173    /// Events associated with this span.
174    span_events: Vec<SpanEvent>,
175}
176
177impl Span {
178    /// Creates a new `Span` with all required fields.
179    #[allow(clippy::too_many_arguments)]
180    pub fn new(
181        service: impl Into<MetaString>, name: impl Into<MetaString>, resource: impl Into<MetaString>,
182        span_type: impl Into<MetaString>, trace_id: u64, span_id: u64, parent_id: u64, start: u64, duration: u64,
183        error: i32,
184    ) -> Self {
185        Self {
186            service: service.into(),
187            name: name.into(),
188            resource: resource.into(),
189            span_type: span_type.into(),
190            trace_id,
191            span_id,
192            parent_id,
193            start,
194            duration,
195            error,
196            ..Self::default()
197        }
198    }
199
200    /// Sets the service name.
201    pub fn with_service(mut self, service: impl Into<MetaString>) -> Self {
202        self.service = service.into();
203        self
204    }
205
206    /// Sets the operation name.
207    pub fn with_name(mut self, name: impl Into<MetaString>) -> Self {
208        self.name = name.into();
209        self
210    }
211
212    /// Sets the resource name.
213    pub fn with_resource(mut self, resource: impl Into<MetaString>) -> Self {
214        self.resource = resource.into();
215        self
216    }
217
218    /// Sets the trace identifier.
219    pub fn with_trace_id(mut self, trace_id: u64) -> Self {
220        self.trace_id = trace_id;
221        self
222    }
223
224    /// Sets the span identifier.
225    pub fn with_span_id(mut self, span_id: u64) -> Self {
226        self.span_id = span_id;
227        self
228    }
229
230    /// Sets the parent span identifier.
231    pub fn with_parent_id(mut self, parent_id: u64) -> Self {
232        self.parent_id = parent_id;
233        self
234    }
235
236    /// Sets the start timestamp.
237    pub fn with_start(mut self, start: u64) -> Self {
238        self.start = start;
239        self
240    }
241
242    /// Sets the span duration.
243    pub fn with_duration(mut self, duration: u64) -> Self {
244        self.duration = duration;
245        self
246    }
247
248    /// Sets the error flag.
249    pub fn with_error(mut self, error: i32) -> Self {
250        self.error = error;
251        self
252    }
253
254    /// Sets the span type (e.g., web, db, lambda).
255    pub fn with_span_type(mut self, span_type: impl Into<MetaString>) -> Self {
256        self.span_type = span_type.into();
257        self
258    }
259
260    /// Replaces the string-valued tag map.
261    pub fn with_meta(mut self, meta: impl Into<Option<FastHashMap<MetaString, MetaString>>>) -> Self {
262        self.meta = meta.into().unwrap_or_default();
263        self
264    }
265
266    /// Replaces the numeric-valued tag map.
267    pub fn with_metrics(mut self, metrics: impl Into<Option<FastHashMap<MetaString, f64>>>) -> Self {
268        self.metrics = metrics.into().unwrap_or_default();
269        self
270    }
271
272    /// Replaces the structured metadata map.
273    pub fn with_meta_struct(mut self, meta_struct: impl Into<Option<FastHashMap<MetaString, Vec<u8>>>>) -> Self {
274        self.meta_struct = meta_struct.into().unwrap_or_default();
275        self
276    }
277
278    /// Replaces the span links collection.
279    pub fn with_span_links(mut self, span_links: impl Into<Option<Vec<SpanLink>>>) -> Self {
280        self.span_links = span_links.into().unwrap_or_default();
281        self
282    }
283
284    /// Replaces the span events collection.
285    pub fn with_span_events(mut self, span_events: impl Into<Option<Vec<SpanEvent>>>) -> Self {
286        self.span_events = span_events.into().unwrap_or_default();
287        self
288    }
289
290    /// Returns the service name.
291    pub fn service(&self) -> &str {
292        &self.service
293    }
294
295    /// Returns the operation name.
296    pub fn name(&self) -> &str {
297        &self.name
298    }
299
300    /// Returns the resource name.
301    pub fn resource(&self) -> &str {
302        &self.resource
303    }
304
305    /// Sets the resource name.
306    pub fn set_resource(&mut self, resource: impl Into<MetaString>) {
307        self.resource = resource.into();
308    }
309
310    /// Returns the trace identifier.
311    pub fn trace_id(&self) -> u64 {
312        self.trace_id
313    }
314
315    /// Returns the span identifier.
316    pub fn span_id(&self) -> u64 {
317        self.span_id
318    }
319
320    /// Returns the parent span identifier.
321    pub fn parent_id(&self) -> u64 {
322        self.parent_id
323    }
324
325    /// Returns the start timestamp.
326    pub fn start(&self) -> u64 {
327        self.start
328    }
329
330    /// Returns the span duration.
331    pub fn duration(&self) -> u64 {
332        self.duration
333    }
334
335    /// Returns the error flag.
336    pub fn error(&self) -> i32 {
337        self.error
338    }
339
340    /// Returns the span type.
341    pub fn span_type(&self) -> &str {
342        &self.span_type
343    }
344
345    /// Returns the string-valued tag map.
346    pub fn meta(&self) -> &FastHashMap<MetaString, MetaString> {
347        &self.meta
348    }
349
350    /// Returns a mutable reference to the meta map.
351    pub fn meta_mut(&mut self) -> &mut FastHashMap<MetaString, MetaString> {
352        &mut self.meta
353    }
354
355    /// Returns the numeric-valued tag map.
356    pub fn metrics(&self) -> &FastHashMap<MetaString, f64> {
357        &self.metrics
358    }
359
360    /// Returns a mutable reference to the metrics map.
361    pub fn metrics_mut(&mut self) -> &mut FastHashMap<MetaString, f64> {
362        &mut self.metrics
363    }
364
365    /// Returns the structured metadata map.
366    pub fn meta_struct(&self) -> &FastHashMap<MetaString, Vec<u8>> {
367        &self.meta_struct
368    }
369
370    /// Returns the span links collection.
371    pub fn span_links(&self) -> &[SpanLink] {
372        &self.span_links
373    }
374
375    /// Returns the span events collection.
376    pub fn span_events(&self) -> &[SpanEvent] {
377        &self.span_events
378    }
379}
380
381/// A link between spans describing a causal relationship.
382#[derive(Clone, Debug, PartialEq, Default)]
383pub struct SpanLink {
384    /// Trace identifier for the linked span.
385    trace_id: u64,
386    /// High bits of the trace identifier when 128-bit IDs are used.
387    trace_id_high: u64,
388    /// Span identifier for the linked span.
389    span_id: u64,
390    /// Additional attributes attached to the link.
391    attributes: FastHashMap<MetaString, MetaString>,
392    /// W3C tracestate value.
393    tracestate: MetaString,
394    /// W3C trace flags where the high bit must be set when provided.
395    flags: u32,
396}
397
398impl SpanLink {
399    /// Creates a new span link for the provided identifiers.
400    pub fn new(trace_id: u64, span_id: u64) -> Self {
401        Self {
402            trace_id,
403            span_id,
404            ..Self::default()
405        }
406    }
407
408    /// Sets the trace identifier.
409    pub fn with_trace_id(mut self, trace_id: u64) -> Self {
410        self.trace_id = trace_id;
411        self
412    }
413
414    /// Sets the high bits of the trace identifier.
415    pub fn with_trace_id_high(mut self, trace_id_high: u64) -> Self {
416        self.trace_id_high = trace_id_high;
417        self
418    }
419
420    /// Sets the span identifier.
421    pub fn with_span_id(mut self, span_id: u64) -> Self {
422        self.span_id = span_id;
423        self
424    }
425
426    /// Replaces the attributes map.
427    pub fn with_attributes(mut self, attributes: impl Into<Option<FastHashMap<MetaString, MetaString>>>) -> Self {
428        self.attributes = attributes.into().unwrap_or_default();
429        self
430    }
431
432    /// Sets the W3C tracestate value.
433    pub fn with_tracestate(mut self, tracestate: impl Into<MetaString>) -> Self {
434        self.tracestate = tracestate.into();
435        self
436    }
437
438    /// Sets the W3C trace flags.
439    pub fn with_flags(mut self, flags: u32) -> Self {
440        self.flags = flags;
441        self
442    }
443
444    /// Returns the trace identifier.
445    pub fn trace_id(&self) -> u64 {
446        self.trace_id
447    }
448
449    /// Returns the high bits of the trace identifier.
450    pub fn trace_id_high(&self) -> u64 {
451        self.trace_id_high
452    }
453
454    /// Returns the span identifier.
455    pub fn span_id(&self) -> u64 {
456        self.span_id
457    }
458
459    /// Returns the attributes map.
460    pub fn attributes(&self) -> &FastHashMap<MetaString, MetaString> {
461        &self.attributes
462    }
463
464    /// Returns the W3C tracestate value.
465    pub fn tracestate(&self) -> &str {
466        &self.tracestate
467    }
468
469    /// Returns the W3C trace flags.
470    pub fn flags(&self) -> u32 {
471        self.flags
472    }
473}
474
475/// An event associated with a span.
476#[derive(Clone, Debug, PartialEq, Default)]
477pub struct SpanEvent {
478    /// Event timestamp in nanoseconds since Unix epoch.
479    time_unix_nano: u64,
480    /// Event name.
481    name: MetaString,
482    /// Arbitrary attributes describing the event.
483    attributes: FastHashMap<MetaString, AttributeValue>,
484}
485
486impl SpanEvent {
487    /// Creates a new span event with the given timestamp and name.
488    pub fn new(time_unix_nano: u64, name: impl Into<MetaString>) -> Self {
489        Self {
490            time_unix_nano,
491            name: name.into(),
492            ..Self::default()
493        }
494    }
495
496    /// Sets the event timestamp.
497    pub fn with_time_unix_nano(mut self, time_unix_nano: u64) -> Self {
498        self.time_unix_nano = time_unix_nano;
499        self
500    }
501
502    /// Sets the event name.
503    pub fn with_name(mut self, name: impl Into<MetaString>) -> Self {
504        self.name = name.into();
505        self
506    }
507
508    /// Replaces the attributes map.
509    pub fn with_attributes(mut self, attributes: impl Into<Option<FastHashMap<MetaString, AttributeValue>>>) -> Self {
510        self.attributes = attributes.into().unwrap_or_default();
511        self
512    }
513
514    /// Returns the event timestamp.
515    pub fn time_unix_nano(&self) -> u64 {
516        self.time_unix_nano
517    }
518
519    /// Returns the event name.
520    pub fn name(&self) -> &str {
521        &self.name
522    }
523
524    /// Returns the attributes map.
525    pub fn attributes(&self) -> &FastHashMap<MetaString, AttributeValue> {
526        &self.attributes
527    }
528}
529
530/// Values supported for span and event attributes.
531#[derive(Clone, Debug, PartialEq)]
532pub enum AttributeValue {
533    /// String attribute value.
534    String(MetaString),
535    /// Boolean attribute value.
536    Bool(bool),
537    /// Integer attribute value.
538    Int(i64),
539    /// Floating-point attribute value.
540    Double(f64),
541    /// Array attribute values.
542    Array(Vec<AttributeScalarValue>),
543}
544
545/// Scalar values supported inside attribute arrays.
546#[derive(Clone, Debug, PartialEq)]
547pub enum AttributeScalarValue {
548    /// String array value.
549    String(MetaString),
550    /// Boolean array value.
551    Bool(bool),
552    /// Integer array value.
553    Int(i64),
554    /// Floating-point array value.
555    Double(f64),
556}