Seregon/StratoSDK

StratoSDK is a framework with a declarative approach similar to Flutter/React, written and designed entirely for Rust.

Rust/27.3 KB/No license
crates/strato-ui-core/src/traces.rs
1use std::sync::{Arc, Mutex};
2 
3use bounded_vec_deque::BoundedVecDeque;
4use instant::Instant;
5use lazy_static::lazy_static;
6 
7lazy_static! {
8 static ref TRACES: Arc<Mutex<Traces>> = Arc::new(Mutex::new(Traces::new()));
9}
10 
11const MAX_BUFFER_SIZE: usize = 1024;
12 
13struct Traces {
14 // Bounded in case we are tracing a lot of events and we don't want to blow
15 // up memory
16 events: BoundedVecDeque<TraceEvent>,
17 end_after_next: Option<&'static str>,
18}
19 
20impl Traces {
21 fn new() -> Self {
22 Self {
23 events: BoundedVecDeque::new(MAX_BUFFER_SIZE),
24 end_after_next: None,
25 }
26 }
27}
28 
29struct TraceEvent {
30 timestamp: Instant,
31 name: &'static str,
32}
33 
34#[macro_export]
35macro_rules! start_trace {
36 ($name:expr) => {
37 #[cfg(feature = "traces")]
38 $crate::traces::start_trace($name)
39 };
40}
41 
42#[macro_export]
43macro_rules! record_trace_event {
44 ($name:expr) => {
45 #[cfg(feature = "traces")]
46 $crate::traces::record_event($name)
47 };
48}
49 
50#[macro_export]
51macro_rules! end_trace_after_next {
52 ($name:expr) => {
53 #[cfg(feature = "traces")]
54 $crate::traces::end_trace_after_next($name)
55 };
56}
57 
58#[macro_export]
59macro_rules! end_trace {
60 () => {
61 #[cfg(feature = "traces")]
62 $crate::traces::end_trace()
63 };
64}
65 
66pub fn start_trace(event_name: &'static str) {
67 TRACES.lock().unwrap().events.clear();
68 record_event(event_name);
69}
70 
71pub fn record_event(name: &'static str) {
72 let should_end = {
73 // Separate block to let the mutex go out of scope before calling end_trace
74 let mut traces = TRACES.lock().unwrap();
75 traces.events.push_back(TraceEvent {
76 name,
77 timestamp: Instant::now(),
78 });
79 
80 traces.end_after_next == Some(name)
81 };
82 if should_end {
83 end_trace();
84 }
85}
86 
87pub fn end_trace_after_next(event_name: &'static str) {
88 TRACES.lock().unwrap().end_after_next = Some(event_name);
89}
90 
91pub fn end_trace() {
92 let mut traces = TRACES.lock().unwrap();
93 let start = traces.events.pop_front().expect("no empty traces");
94 for event in traces.events.iter() {
95 println!(
96 "[{:.4} ms] {} ",
97 (event.timestamp.duration_since(start.timestamp).as_micros() as f32 / 1000.),
98 event.name,
99 );
100 }
101 traces.end_after_next = None;
102 traces.events.clear();
103}
104