1use crate::clocks::Clock;
2use crate::id_generators::IdGenerator;
3use crate::sampling::{Sampler, SamplingDecision, SamplingResult, StaticSampler};
4use crate::span_collections::SpanCollection;
5use crate::spinlock::Spinlock;
6use crate::{tracer::*, Severity};
7
8fn default_instrumentation_error_handler(err: InstrumentationError){
9 eprintln!("[ERROR] tracelite: instrumentation error: {err}");
10}
11
12pub struct DefaultTracerConfig<C, IG, SS, S, SC, X> {
13 clock: C,
14 id_generator: IG,
15 static_sampler: SS,
16 sampler: S,
17 collection: SC,
18 export_sink: X,
19 default_span_kind: Option<SpanKind>,
20 on_instrumentation_error: Box<dyn Fn(InstrumentationError) + Send + Sync>
21}
22
23impl<C, IG, SS, S, SC, X> DefaultTracerConfig<C, IG, SS, S, SC, X>
24 where C: Clock, IG: IdGenerator, SS: StaticSampler, S: Sampler, SC: SpanCollection, X: Fn(SC::Exportable) + Send + Sync + 'static
25{
26 pub fn new(clock: C, id_generator: IG, static_sampler: SS, sampler: S, collection: SC, export_sink: X) -> Self {
27 Self{
28 clock,
29 id_generator,
30 static_sampler,
31 sampler,
32 collection,
33 export_sink,
34 default_span_kind: None,
35 on_instrumentation_error: Box::new(default_instrumentation_error_handler),
36 }
37 }
38
39 pub fn install(self){
40 let tracer = DefaultTracer{
41 clock: self.clock,
42 id_generator: self.id_generator,
43 static_sampler: self.static_sampler,
44 sampler: self.sampler,
45 spans: Spinlock::new(self.collection),
46 export_sink: self.export_sink,
47 default_span_kind: self.default_span_kind,
48 on_instrumentation_error: self.on_instrumentation_error
49 };
50 globals::set_tracer(Box::new(tracer));
51 }
52
53 pub fn sampler<S2>(self, sampler: S2) -> DefaultTracerConfig<C, IG, SS, S2, SC, X> {
54 DefaultTracerConfig{
55 clock: self.clock,
56 id_generator: self.id_generator,
57 static_sampler: self.static_sampler,
58 sampler,
59 collection: self.collection,
60 export_sink: self.export_sink,
61 default_span_kind: self.default_span_kind,
62 on_instrumentation_error: self.on_instrumentation_error
63 }
64 }
65
66 pub fn default_span_kind(self, kind: SpanKind) -> Self {
67 Self{ default_span_kind: Some(kind), ..self }
68 }
69
70 pub fn on_instrumentation_error(self, f: impl Fn(InstrumentationError) + Send + Sync + 'static) -> Self {
71 Self{ on_instrumentation_error: Box::new(f), ..self }
72 }
73}
74
75pub struct DefaultTracer<C, IG, SS, S, SC, X> {
76 clock: C,
77 id_generator: IG,
78 static_sampler: SS,
79 sampler: S,
80 spans: Spinlock<SC>,
82 export_sink: X,
83 default_span_kind: Option<SpanKind>,
84 on_instrumentation_error: Box<dyn Fn(InstrumentationError) + Send + Sync>
85}
86
87impl<C, IG, SS, S, SC, X> Tracer for DefaultTracer<C, IG, SS, S, SC, X>
88 where C: Clock, IG: IdGenerator, SS: StaticSampler, S: Sampler, SC: SpanCollection, X: Fn(SC::Exportable) + Send + Sync + 'static
89{
90 fn is_enabled(&self, target: Option<&str>, severity: Option<Severity>) -> bool {
91 self.static_sampler.is_enabled(target, severity)
92 }
93
94 fn start_span(&self, mut args: SpanArgs, _: &mut PrivateMarker) -> Option<(RecordingSpanContext, SamplingResult)> {
95 let sampling = self.sampler.should_sample(&args);
96 match sampling.decision {
97 SamplingDecision::Drop => return None,
98 SamplingDecision::RecordOnly => {}, SamplingDecision::RecordAndSample => {},
100 }
101
102 args.kind = args.kind.or(self.default_span_kind);
104
105 let trace_id = args.parent.as_ref()
107 .map(|p| p.trace_id)
108 .unwrap_or_else(|| self.id_generator.new_trace_id());
109 let span_id = self.id_generator.new_span_id();
110
111 let span_context = SpanContext{ trace_id, span_id, trace_flags: 1 };
112 let opened_at = self.clock.now_unix_nano();
113
114 let Some(collect_idx) = self.spans.lock().open_span(trace_id, span_id, args, opened_at).ok() else {
116 todo!() };
118
119 Some((RecordingSpanContext{ span_context, collect_idx }, sampling))
120 }
121
122 fn set_attributes(&self, span: RecordingSpanContext, attrs: AttributeList) {
123 let _result = self.spans.lock().set_attributes(span.collect_idx, attrs); }
125
126 fn add_event(&self, span: RecordingSpanContext, args: EventArgs, _: &mut PrivateMarker) {
127 let occurs_at = self.clock.now_unix_nano();
128 let _result = self.spans.lock().add_event(span.collect_idx, args, occurs_at); }
130
131 fn set_status(&self, span: RecordingSpanContext, status: SpanStatus) {
132 let _result = self.spans.lock().set_status(span.collect_idx, status); }
134
135 fn drop_span(&self, span: RecordingSpanContext, _ : &mut PrivateMarker) {
136 let dropped_at = self.clock.now_unix_nano();
137 self.spans.lock().drop_span(span.collect_idx, dropped_at, &self.export_sink);
138 }
139
140 fn flush(&self) {
141 println!("[DEBUG] tracelite: flush");
142 self.spans.lock().flush(&self.export_sink);
143 }
144
145 fn instrumentation_error(&self, err: InstrumentationError) {
146 (self.on_instrumentation_error)(err)
147 }
148}