Skip to main content

micromegas_tracing/spans/
block.rs

1use super::{
2    BeginAsyncDynNamedSpanEvent, BeginAsyncNamedSpanEvent, BeginAsyncSpanEvent,
3    BeginThreadDynNamedSpanEvent, BeginThreadNamedSpanEvent, BeginThreadSpanEvent,
4    EndAsyncDynNamedSpanEvent, EndAsyncNamedSpanEvent, EndAsyncSpanEvent,
5    EndThreadDynNamedSpanEvent, EndThreadNamedSpanEvent, EndThreadSpanEvent, SpanLocation,
6    SpanLocationRecord, SpanMetadata, SpanRecord,
7};
8use crate::{
9    dyn_deps::DynDeps,
10    event::{EventBlock, EventStream, ExtractDeps},
11    property_set::StringDepsQueue,
12    string_id::{DynStringId, StringId},
13};
14use micromegas_transit::{StaticStringDependency, Utf8StaticStringDependency, prelude::*};
15use std::collections::HashSet;
16
17declare_queue_struct!(
18    struct ThreadEventQueue<
19        BeginThreadSpanEvent,
20        EndThreadSpanEvent,
21        BeginThreadNamedSpanEvent,
22        EndThreadNamedSpanEvent,
23        BeginAsyncSpanEvent,
24        EndAsyncSpanEvent,
25        BeginAsyncNamedSpanEvent,
26        EndAsyncNamedSpanEvent,
27        BeginThreadDynNamedSpanEvent,
28        EndThreadDynNamedSpanEvent,
29        BeginAsyncDynNamedSpanEvent,
30        EndAsyncDynNamedSpanEvent,
31    > {}
32);
33
34declare_queue_struct!(
35    struct ThreadDepsQueue<
36        SpanRecord,
37        SpanLocationRecord,
38        Utf8StaticStringDependency,
39        StaticStringDependency,
40    > {}
41);
42
43impl StringDepsQueue for ThreadDepsQueue {
44    fn push_string(&mut self, dep: StaticStringDependency) {
45        self.push(dep);
46    }
47}
48
49fn record_scope_event_dependencies(
50    thread_span_desc: &'static SpanMetadata,
51    recorded_deps: &mut HashSet<u64>,
52    deps: &mut ThreadDepsQueue,
53) {
54    let thread_span_ptr = thread_span_desc as *const _ as u64;
55    if recorded_deps.insert(thread_span_ptr) {
56        let name = Utf8StaticStringDependency::from(thread_span_desc.name);
57        if recorded_deps.insert(name.ptr as u64) {
58            deps.push(name);
59        }
60        let target = Utf8StaticStringDependency::from(thread_span_desc.location.target);
61        if recorded_deps.insert(target.ptr as u64) {
62            deps.push(target);
63        }
64        let module_path = Utf8StaticStringDependency::from(thread_span_desc.location.module_path);
65        if recorded_deps.insert(module_path.ptr as u64) {
66            deps.push(module_path);
67        }
68        let file = Utf8StaticStringDependency::from(thread_span_desc.location.file);
69        if recorded_deps.insert(file.ptr as u64) {
70            deps.push(file);
71        }
72        deps.push(SpanRecord {
73            id: thread_span_ptr,
74            name: thread_span_desc.name.as_ptr(),
75            target: thread_span_desc.location.target.as_ptr(),
76            module_path: thread_span_desc.location.module_path.as_ptr(),
77            file: thread_span_desc.location.file.as_ptr(),
78            line: thread_span_desc.location.line,
79            lod: thread_span_desc.location.lod as u32,
80        });
81    }
82}
83
84fn record_span_location_dependencies(
85    thread_span_location: &'static SpanLocation,
86    recorded_deps: &mut HashSet<u64>,
87    deps: &mut ThreadDepsQueue,
88) {
89    let location_id = thread_span_location as *const _ as u64;
90    if recorded_deps.insert(location_id) {
91        let target = Utf8StaticStringDependency::from(thread_span_location.target);
92        if recorded_deps.insert(target.ptr as u64) {
93            deps.push(target);
94        }
95        let module_path = Utf8StaticStringDependency::from(thread_span_location.module_path);
96        if recorded_deps.insert(module_path.ptr as u64) {
97            deps.push(module_path);
98        }
99        let file = Utf8StaticStringDependency::from(thread_span_location.file);
100        if recorded_deps.insert(file.ptr as u64) {
101            deps.push(file);
102        }
103        deps.push(SpanLocationRecord {
104            id: location_id,
105            target: thread_span_location.target.as_ptr(),
106            module_path: thread_span_location.module_path.as_ptr(),
107            file: thread_span_location.file.as_ptr(),
108            line: thread_span_location.line,
109            lod: thread_span_location.lod as u32,
110        });
111    }
112}
113
114fn record_named_scope_event_dependencies(
115    thread_span_location: &'static SpanLocation,
116    name: &StringId,
117    recorded_deps: &mut HashSet<u64>,
118    deps: &mut ThreadDepsQueue,
119) {
120    record_span_location_dependencies(thread_span_location, recorded_deps, deps);
121    if recorded_deps.insert(name.id()) {
122        deps.push(Utf8StaticStringDependency::from(name));
123    }
124}
125
126impl ExtractDeps for ThreadEventQueue {
127    type DepsQueue = ThreadDepsQueue;
128
129    fn extract(&self, dyn_deps: &DynDeps<Self::DepsQueue>) -> Self::DepsQueue {
130        let mut deps = ThreadDepsQueue::new(1024 * 1024);
131        let mut recorded_deps = HashSet::new();
132        for x in self.iter() {
133            match x {
134                ThreadEventQueueAny::BeginThreadSpanEvent(evt) => {
135                    record_scope_event_dependencies(
136                        evt.thread_span_desc,
137                        &mut recorded_deps,
138                        &mut deps,
139                    );
140                }
141                ThreadEventQueueAny::EndThreadSpanEvent(evt) => {
142                    record_scope_event_dependencies(
143                        evt.thread_span_desc,
144                        &mut recorded_deps,
145                        &mut deps,
146                    );
147                }
148                ThreadEventQueueAny::BeginThreadNamedSpanEvent(evt) => {
149                    record_named_scope_event_dependencies(
150                        evt.thread_span_location,
151                        &evt.name,
152                        &mut recorded_deps,
153                        &mut deps,
154                    );
155                }
156                ThreadEventQueueAny::EndThreadNamedSpanEvent(evt) => {
157                    record_named_scope_event_dependencies(
158                        evt.thread_span_location,
159                        &evt.name,
160                        &mut recorded_deps,
161                        &mut deps,
162                    );
163                }
164                ThreadEventQueueAny::BeginAsyncSpanEvent(evt) => {
165                    record_scope_event_dependencies(evt.span_desc, &mut recorded_deps, &mut deps);
166                }
167                ThreadEventQueueAny::EndAsyncSpanEvent(evt) => {
168                    record_scope_event_dependencies(evt.span_desc, &mut recorded_deps, &mut deps);
169                }
170                ThreadEventQueueAny::BeginAsyncNamedSpanEvent(evt) => {
171                    record_named_scope_event_dependencies(
172                        evt.span_location,
173                        &evt.name,
174                        &mut recorded_deps,
175                        &mut deps,
176                    );
177                }
178                ThreadEventQueueAny::EndAsyncNamedSpanEvent(evt) => {
179                    record_named_scope_event_dependencies(
180                        evt.span_location,
181                        &evt.name,
182                        &mut recorded_deps,
183                        &mut deps,
184                    );
185                }
186                ThreadEventQueueAny::BeginThreadDynNamedSpanEvent(evt) => {
187                    record_span_location_dependencies(
188                        evt.thread_span_location,
189                        &mut recorded_deps,
190                        &mut deps,
191                    );
192                }
193                ThreadEventQueueAny::EndThreadDynNamedSpanEvent(evt) => {
194                    record_span_location_dependencies(
195                        evt.thread_span_location,
196                        &mut recorded_deps,
197                        &mut deps,
198                    );
199                }
200                ThreadEventQueueAny::BeginAsyncDynNamedSpanEvent(evt) => {
201                    record_span_location_dependencies(
202                        evt.span_location,
203                        &mut recorded_deps,
204                        &mut deps,
205                    );
206                }
207                ThreadEventQueueAny::EndAsyncDynNamedSpanEvent(evt) => {
208                    record_span_location_dependencies(
209                        evt.span_location,
210                        &mut recorded_deps,
211                        &mut deps,
212                    );
213                }
214            }
215        }
216        deps.extend_from(dyn_deps.queue());
217        deps
218    }
219}
220
221pub type ThreadBlock = EventBlock<ThreadEventQueue>;
222pub type ThreadStream = EventStream<ThreadBlock>;
223
224impl ThreadStream {
225    /// Writes `name` to the current block's dynamic queue, then pushes the event built from its id.
226    pub fn push_dyn_named<T>(&mut self, name: &str, make: impl FnOnce(DynStringId) -> T)
227    where
228        T: InProcSerialize + ThreadEventQueueTypeIndex,
229    {
230        let (events, dyn_deps) = self.get_block_mut_parts();
231        let id = dyn_deps.intern_str(name);
232        events.push(make(DynStringId { id }));
233    }
234}