1use std::cell::RefCell;
4use std::collections::HashMap;
5use std::rc::Rc;
6
7use crate::entity::Capacity;
8use crate::perfetto_trace_builder::PerfettoTraceBuilder;
9use crate::tracker::EntityManager;
10use crate::tracker::aka::AlternativeNames;
11use crate::{Id, SharedWriter, Track, Writer};
12
13pub struct PerfettoTracker {
15 entity_manager: EntityManager,
16 writer: SharedWriter,
17 current_time_ns: RefCell<u64>,
18 trace_builder: RefCell<PerfettoTraceBuilder>,
19 group_memberships: RefCell<HashMap<Id, Id>>,
20 activity_lanes: RefCell<HashMap<Id, Id>>,
21}
22
23impl PerfettoTracker {
24 pub fn new(entity_manager: EntityManager, writer: Writer) -> Self {
26 Self {
27 entity_manager,
28 writer: Rc::new(RefCell::new(writer)),
29 current_time_ns: RefCell::new(0),
30 trace_builder: RefCell::new(PerfettoTraceBuilder::new()),
31 group_memberships: RefCell::new(HashMap::new()),
32 activity_lanes: RefCell::new(HashMap::new()),
33 }
34 }
35}
36
37impl Track for PerfettoTracker {
38 fn unique_id(&self) -> Id {
39 self.entity_manager.unique_id()
40 }
41
42 fn enabled_level(&self, id: Id) -> log::Level {
43 self.entity_manager.enabled_level(id)
44 }
45
46 fn monitoring_window_size_for(&self, id: Id) -> Option<u64> {
47 self.entity_manager.monitoring_window_size_for(id)
48 }
49
50 fn add_entity(
51 &self,
52 id: Id,
53 entity_name: &str,
54 alternative_names: AlternativeNames,
55 ) -> log::Level {
56 self.entity_manager
57 .add_entity(id, entity_name, alternative_names)
58 }
59
60 fn enter(&self, id: Id, entered: Id) {
61 if self.is_entity_enabled(id, log::Level::Trace) {
62 let guard = self.trace_builder.borrow_mut();
63 let trace_packet = guard.build_enter_track_event_trace_packet(
64 *self.current_time_ns.borrow(),
65 id,
66 entered,
67 );
68 let buf = guard.build_trace_to_bytes(vec![trace_packet]);
69 self.writer.borrow_mut().write_all(&buf).unwrap();
70 }
71 }
72
73 fn exit(&self, id: Id, exited: Id) {
74 if self.is_entity_enabled(id, log::Level::Trace) {
75 let guard = self.trace_builder.borrow_mut();
76 let trace_packet = guard.build_exit_track_event_trace_packet(
77 *self.current_time_ns.borrow(),
78 id,
79 exited,
80 );
81 let buf = guard.build_trace_to_bytes(vec![trace_packet]);
82 self.writer.borrow_mut().write_all(&buf).unwrap();
83 }
84 }
85
86 fn value(&self, id: Id, value: f64) {
87 if self.is_entity_enabled(id, log::Level::Trace) {
88 let guard = self.trace_builder.borrow_mut();
89 let trace_packet = guard.build_value_track_event_trace_packet(
90 *self.current_time_ns.borrow(),
91 id,
92 value,
93 );
94 let buf = guard.build_trace_to_bytes(vec![trace_packet]);
95 self.writer.borrow_mut().write_all(&buf).unwrap();
96 }
97 }
98
99 fn begin_activity(&self, activity: Id, lane: Id, name: &str) {
100 if self.is_entity_enabled(lane, log::Level::Trace) {
101 self.activity_lanes.borrow_mut().insert(activity, lane);
102 let guard = self.trace_builder.borrow_mut();
103 let correlation_id = self
104 .group_memberships
105 .borrow()
106 .get(&activity)
107 .map(|group_id| group_id.0);
108 let trace_packet = guard.build_activity_begin_trace_packet(
109 *self.current_time_ns.borrow(),
110 lane,
111 name,
112 correlation_id,
113 );
114 let buf = guard.build_trace_to_bytes(vec![trace_packet]);
115 self.writer.borrow_mut().write_all(&buf).unwrap();
116 }
117 }
118
119 fn add_to_group(&self, activity: Id, group_id: Id) {
120 self.group_memberships
121 .borrow_mut()
122 .insert(activity, group_id);
123 }
124
125 fn remove_from_group(&self, activity: Id, group_id: Id) {
126 let is_member = self.group_memberships.borrow().get(&activity) == Some(&group_id);
127 if is_member {
128 self.group_memberships.borrow_mut().remove(&activity);
129 }
130 }
131
132 fn end_activity(&self, activity: Id) {
133 if let Some(lane) = self.activity_lanes.borrow_mut().remove(&activity)
134 && self.is_entity_enabled(lane, log::Level::Trace)
135 {
136 let guard = self.trace_builder.borrow_mut();
137 let trace_packet =
138 guard.build_activity_end_trace_packet(*self.current_time_ns.borrow(), lane);
139 let buf = guard.build_trace_to_bytes(vec![trace_packet]);
140 self.writer.borrow_mut().write_all(&buf).unwrap();
141 }
142 }
143
144 fn create_entity(&self, created_by: Id, id: Id, name: &str) {
145 if self.is_entity_enabled(id, log::Level::Trace) {
146 let mut guard = self.trace_builder.borrow_mut();
147 let trace_packet = guard.build_enter_exit_track_descriptor_trace_packet(
148 *self.current_time_ns.borrow(),
149 id,
150 created_by,
151 name,
152 );
153 let buf = guard.build_trace_to_bytes(vec![trace_packet]);
154 self.writer.borrow_mut().write_all(&buf).unwrap();
155 }
156 }
157
158 fn create_monitor(&self, created_by: Id, id: Id, name: &str) {
159 if self.is_entity_enabled(id, log::Level::Trace) {
160 let mut guard = self.trace_builder.borrow_mut();
161 let trace_packet = guard.build_value_track_descriptor_trace_packet(
162 *self.current_time_ns.borrow(),
163 id,
164 created_by,
165 name,
166 );
167 let buf = guard.build_trace_to_bytes(vec![trace_packet]);
168 self.writer.borrow_mut().write_all(&buf).unwrap();
169 }
170 }
171
172 fn create_lane(&self, created_by: Id, id: Id, name: &str) {
173 if self.is_entity_enabled(id, log::Level::Trace) {
174 let mut guard = self.trace_builder.borrow_mut();
175 let trace_packet = guard.build_activity_track_descriptor_trace_packet(
176 *self.current_time_ns.borrow(),
177 id,
178 created_by,
179 name,
180 );
181 let buf = guard.build_trace_to_bytes(vec![trace_packet]);
182 self.writer.borrow_mut().write_all(&buf).unwrap();
183 }
184 }
185
186 fn create_group(&self, _created_by: Id, _id: Id, _name: &str) {}
187
188 fn create_object(
189 &self,
190 created_by: Id,
191 id: Id,
192 _size: usize,
193 _units: &str,
194 _req_type: u8,
195 details: &str,
196 ) {
197 if self.is_entity_enabled(created_by, log::Level::Trace) {
198 let mut guard = self.trace_builder.borrow_mut();
199 let trace_packet = guard.build_enter_exit_track_descriptor_trace_packet(
200 *self.current_time_ns.borrow(),
201 id,
202 created_by,
203 details,
204 );
205 let buf = guard.build_trace_to_bytes(vec![trace_packet]);
206 self.writer.borrow_mut().write_all(&buf).unwrap();
207 }
208 }
209
210 fn capacity(&self, _id: Id, _capacity: Capacity) {
211 }
213
214 fn destroy(&self, _destroyed_by: Id, _destroyed_obj: Id) {
215 }
217
218 fn connect(&self, _connect_from: Id, _connect_to: Id) {
219 }
221
222 fn log(&self, _msg_by: Id, _level: log::Level, _msg: std::fmt::Arguments) {
223 }
225
226 fn time(&self, _set_by: Id, time_ns: f64) {
227 *self.current_time_ns.borrow_mut() = time_ns as u64;
228 }
229
230 fn shutdown(&self) {
231 }
233}