1pub use coz::thread_init;
15use coz::Counter;
16
17use std::sync::atomic::{Ordering, AtomicUsize};
18
19use tracing::{
20 Id, Metadata, Event,
21 span,
22 subscriber::{self, Subscriber},
23};
24
25use chashmap::CHashMap;
26
27struct ThroughputCounter {
28 start: Counter,
29 end: Counter,
30}
31
32impl ThroughputCounter {
33 fn new(name: &'static str) -> Self {
34 ThroughputCounter {
35 start: Counter::begin(name),
36 end: Counter::end(name),
37 }
38 }
39}
40
41pub struct TracingCozBridge {
43 next_id: AtomicUsize,
44 latency_counters: CHashMap<&'static str, Counter>,
45 throughput_counters: CHashMap<Id, ThroughputCounter>,
46 idents: CHashMap<&'static str, Id>,
47}
48
49impl TracingCozBridge {
50 pub fn new() -> Self {
52 TracingCozBridge {
53 next_id: AtomicUsize::new(1),
54 latency_counters: CHashMap::new(),
55 throughput_counters: CHashMap::new(),
56 idents: CHashMap::new(),
57 }
58 }
59
60 fn next_id(&self) -> Id {
61 Id::from_u64(self.next_id.fetch_add(1, Ordering::SeqCst) as u64)
62 }
63}
64
65impl Subscriber for TracingCozBridge {
66 fn register_callsite(&self, _meta: &Metadata<'_>) -> subscriber::Interest {
67 subscriber::Interest::always()
68 }
69
70 fn new_span(&self, new_span: &span::Attributes<'_>) -> Id {
71 let name = new_span.metadata().name();
72 let throughput_counters = &self.throughput_counters;
73 self.idents.upsert(name, || {
74 let next_id = self.next_id();
75 throughput_counters.upsert(next_id.clone(), || ThroughputCounter::new(name), |_| ());
76 next_id
77 }, |_| ());
78
79 (*self.idents.get(name).unwrap()).clone()
80 }
81
82 fn record_follows_from(&self, _span: &Id, _follows: &Id) {
83 }
85
86 fn record(&self, _: &Id, _values: &span::Record<'_>) {
87 }
89
90 fn event(&self, event: &Event<'_>) {
91 let name = event.metadata().name();
92 self.latency_counters.upsert(name, || Counter::progress(name), |cnt| cnt.increment());
93 }
94
95 fn enabled(&self, _metadata: &Metadata<'_>) -> bool {
96 true
97 }
98
99 fn enter(&self, span: &Id) {
100 self.throughput_counters.get(span).unwrap().start.increment()
101 }
102
103 fn exit(&self, span: &Id) {
104 self.throughput_counters.get(span).unwrap().end.increment()
105 }
106}