Skip to main content

kairoi/
span.rs

1use crate::{Event, Node};
2use lazy_static::lazy_static;
3use std::sync::{Arc, Weak};
4use std::time::SystemTime;
5use tokio::task_local;
6
7#[derive(Debug, Copy, Clone)]
8pub struct Progress {
9    total: u64,
10    progress: u64,
11}
12
13impl Progress {
14    pub fn new(total: u64, progress: u64) -> Self {
15        Self { total, progress }
16    }
17
18    pub fn total(&self) -> u64 {
19        self.total
20    }
21
22    pub fn progress(&self) -> u64 {
23        self.progress
24    }
25}
26
27#[derive(Debug, Clone)]
28pub struct Span {
29    timestamp: SystemTime,
30    name: String,
31    progress: Option<Progress>,
32}
33
34pub type SpanRef = Arc<Node<Span>>;
35
36impl Span {
37    pub fn with_name(&self, name: String) -> Self {
38        let mut clone = self.clone();
39        clone.name = name;
40        clone
41    }
42
43    pub fn with_progress(&self, progress: Progress) -> Self {
44        let mut clone = self.clone();
45        clone.progress = Some(progress);
46        clone
47    }
48
49    pub fn timestamp(&self) -> SystemTime {
50        self.timestamp
51    }
52
53    pub fn name(&self) -> &str {
54        &self.name
55    }
56
57    pub fn progress(&self) -> Option<Progress> {
58        self.progress
59    }
60}
61
62impl Default for Span {
63    fn default() -> Self {
64        Self {
65            timestamp: SystemTime::now(),
66            name: String::default(),
67            progress: None,
68        }
69    }
70}
71
72lazy_static! {
73    static ref ROOT: SpanRef = Arc::new(Node::new(Span::default()));
74}
75
76task_local! {
77    static CURRENT: Weak<Node<Span >>;
78}
79
80impl Span {
81    pub async fn scope<T, F: AsyncFnOnce(Scope) -> T>(f: F) -> T {
82        let new = Self::current().add(Node::new(Self::default()));
83
84        Event::span_begin(new.clone()).submit();
85
86        let new_clone = new.clone();
87        let v = CURRENT
88            .scope(Arc::downgrade(&new_clone), async move {
89                f(Scope::new(new_clone)).await
90            })
91            .await;
92
93        new.delete();
94        Event::span_end(new).submit();
95
96        v
97    }
98
99    pub fn current() -> SpanRef {
100        CURRENT
101            .try_with(|v| v.upgrade())
102            .ok()
103            .flatten()
104            .unwrap_or_else(|| ROOT.clone())
105    }
106
107    pub fn root() -> SpanRef {
108        ROOT.clone()
109    }
110}
111
112pub struct Scope {
113    node: SpanRef,
114}
115
116impl Scope {
117    fn new(node: SpanRef) -> Self {
118        Self { node }
119    }
120
121    pub fn update(&self, data: Span) {
122        self.node.update(data);
123    }
124}