1use std::cell::RefCell;
4use std::rc::Rc;
5
6use capnp::serialize_packed;
7
8use crate::entity::Capacity;
9use crate::gwr_track_capnp::event;
10use crate::gwr_track_capnp::log::LogLevel;
11use crate::tracker::aka::AlternativeNames;
12use crate::tracker::{EntityManager, Track};
13use crate::{Id, SharedWriter, Writer, gwr_track_capnp};
14
15pub struct CapnProtoTracker {
17 entity_manager: EntityManager,
18 writer: SharedWriter,
19}
20
21impl CapnProtoTracker {
22 pub fn new(entity_manager: EntityManager, writer: Writer) -> Self {
24 Self {
25 entity_manager,
26 writer: Rc::new(RefCell::new(writer)),
27 }
28 }
29
30 fn write_event<F>(&self, id: Id, build: F)
39 where
40 F: FnOnce(gwr_track_capnp::event::Builder<'_>),
41 {
42 let mut builder = capnp::message::Builder::new_default();
43 {
44 let mut event = builder.init_root::<event::Builder>();
45 event.set_id(id.0);
46
47 build(event);
49 }
50
51 let mut writer_ref = self.writer.borrow_mut();
53 serialize_packed::write_message(&mut *writer_ref, &builder).unwrap();
54 }
55}
56
57impl Track for CapnProtoTracker {
64 fn unique_id(&self) -> Id {
65 self.entity_manager.unique_id()
66 }
67
68 fn enabled_level(&self, id: Id) -> log::Level {
69 self.entity_manager.enabled_level(id)
70 }
71
72 fn monitoring_window_size_for(&self, id: Id) -> Option<u64> {
73 self.entity_manager.monitoring_window_size_for(id)
74 }
75
76 fn add_entity(
77 &self,
78 id: Id,
79 entity_name: &str,
80 alternative_names: AlternativeNames,
81 ) -> log::Level {
82 self.entity_manager
83 .add_entity(id, entity_name, alternative_names)
84 }
85
86 fn enter(&self, id: Id, object: Id) {
87 if self.is_entity_enabled(id, log::Level::Trace) {
88 self.write_event(id, |mut event| {
89 event.set_enter(object.0);
90 });
91 }
92 }
93
94 fn exit(&self, id: Id, object: Id) {
95 if self.is_entity_enabled(id, log::Level::Trace) {
96 self.write_event(id, |mut event| {
97 event.set_exit(object.0);
98 });
99 }
100 }
101
102 fn value(&self, id: Id, value: f64) {
103 if self.is_entity_enabled(id, log::Level::Trace) {
104 self.write_event(id, |mut event| {
105 event.set_value(value);
106 });
107 }
108 }
109
110 fn begin_activity(&self, activity: Id, lane: Id, name: &str) {
111 if self.is_entity_enabled(lane, log::Level::Trace) {
112 self.write_event(activity, |event| {
113 let mut begin_activity = event.init_begin_activity();
114 begin_activity.set_lane(lane.0);
115 begin_activity.set_name(name);
116 });
117 }
118 }
119
120 fn add_to_group(&self, activity: Id, group_id: Id) {
121 self.write_event(activity, |mut event| {
122 event.set_add_to_group(group_id.0);
123 });
124 }
125
126 fn remove_from_group(&self, activity: Id, group_id: Id) {
127 self.write_event(activity, |mut event| {
128 event.set_remove_from_group(group_id.0);
129 });
130 }
131
132 fn end_activity(&self, activity: Id) {
133 self.write_event(activity, |mut event| {
134 event.set_end_activity(());
135 });
136 }
137
138 fn create_entity(&self, created_by: Id, id: Id, name: &str) {
139 self.write_event(created_by, |event| {
141 let mut create = event.init_create();
142 create.set_id(id.0);
143 create.init_entity().set_name(name);
144 });
145 }
146
147 fn create_monitor(&self, created_by: Id, id: Id, name: &str) {
148 self.write_event(created_by, |event| {
150 let mut create = event.init_create();
151 create.set_id(id.0);
152 create.init_monitor().set_name(name);
153 });
154 }
155
156 fn create_lane(&self, created_by: Id, id: Id, name: &str) {
157 self.write_event(created_by, |event| {
159 let mut create = event.init_create();
160 create.set_id(id.0);
161 create.init_lane().set_name(name);
162 });
163 }
164
165 fn create_group(&self, created_by: Id, id: Id, name: &str) {
166 self.write_event(created_by, |event| {
168 let mut create = event.init_create();
169 create.set_id(id.0);
170 create.init_group().set_name(name);
171 });
172 }
173
174 fn create_object(
175 &self,
176 created_by: Id,
177 id: Id,
178 size: usize,
179 units: &str,
180 req_type: u8,
181 details: &str,
182 ) {
183 if self.is_entity_enabled(created_by, log::Level::Trace) {
184 self.write_event(created_by, |event| {
185 let mut create = event.init_create();
186 create.set_id(id.0);
187 let mut object = create.init_object();
188 object.set_size(size as u64);
189 object.set_units(units);
190 object.set_type(req_type);
191 object.set_details(details);
192 });
193 }
194 }
195
196 fn capacity(&self, id: Id, capacity: Capacity) {
197 self.write_event(id, |event| {
199 let mut event_capacity = event.init_capacity();
200 event_capacity.set_value(capacity.value as u64);
201 event_capacity.set_units(&capacity.units);
202 });
203 }
204
205 fn destroy(&self, destroyed_by: Id, id: Id) {
206 if self.is_entity_enabled(id, log::Level::Trace) {
207 self.write_event(destroyed_by, |mut event| {
208 event.set_destroy(id.0);
209 });
210 }
211 }
212
213 fn connect(&self, connect_from: Id, connect_to: Id) {
214 if self.is_entity_enabled(connect_from, log::Level::Trace)
215 || self.is_entity_enabled(connect_to, log::Level::Trace)
216 {
217 self.write_event(connect_from, |mut event| {
218 event.set_connect(connect_to.0);
219 });
220 }
221 }
222
223 fn log(&self, id: Id, level: log::Level, msg: std::fmt::Arguments) {
224 if self.is_entity_enabled(id, level) {
225 self.write_event(id, |event| {
226 let mut log = event.init_log();
227 let txt = format!("{msg}");
228 log.set_message(&txt);
229 log.set_level(to_capnp_log_level(level));
230 });
231 }
232 }
233
234 fn time(&self, set_by: Id, time_ns: f64) {
235 self.write_event(set_by, |mut event| {
236 event.set_time(time_ns);
237 });
238 }
239
240 fn shutdown(&self) {
241 self.writer.borrow_mut().flush().unwrap();
242 }
243}
244
245fn to_capnp_log_level(level: log::Level) -> LogLevel {
246 match level {
247 log::Level::Error => LogLevel::Error,
248 log::Level::Warn => LogLevel::Warn,
249 log::Level::Info => LogLevel::Info,
250 log::Level::Debug => LogLevel::Debug,
251 log::Level::Trace => LogLevel::Trace,
252 }
253}