1use std::fmt;
10use std::rc::Rc;
11
12use crate::tracker::aka::{Aka, get_alternative_names};
13use crate::{Id, Tracker, create_id, destroy, trace};
14
15#[derive(Clone, Debug, PartialEq, Eq)]
17pub struct Capacity {
18 pub value: usize,
20
21 pub units: String,
23}
24
25impl Capacity {
26 #[must_use]
28 pub fn new(value: usize, units: impl Into<String>) -> Self {
29 Self {
30 value,
31 units: units.into(),
32 }
33 }
34}
35
36pub struct Entity {
45 pub name: String,
47
48 pub parent: Option<Rc<Entity>>,
50
51 pub id: Id,
53
54 pub tracker: Tracker,
56
57 enabled_level: log::Level,
59}
60
61static JOIN: &str = "::";
62
63impl Entity {
64 #[must_use]
66 pub fn new(parent: &Rc<Entity>, name: &str) -> Self {
67 Self::new_with_renames(parent, name, None)
68 }
69
70 #[must_use]
72 pub fn new_with_renames(parent: &Rc<Entity>, name: &str, aka: Option<&Aka>) -> Self {
73 let alternative_names = get_alternative_names(aka, name);
74 let mut full_name = parent.full_name();
75 full_name.push_str(JOIN);
76 full_name.push_str(name);
77
78 let tracker = parent.tracker.clone();
79 let id = create_id!(parent);
80 let enabled_level = tracker.add_entity(id, &full_name, alternative_names);
81
82 let entity = Self {
83 name: String::from(name),
84 parent: Some(parent.clone()),
85 id,
86 tracker,
87 enabled_level,
88 };
89 entity.track_create(parent.id, &full_name);
90
91 if let Some(alternative_names) = alternative_names {
92 for name in alternative_names {
93 trace!(entity ; "aka {name}");
94 }
95 }
96
97 entity
98 }
99
100 #[must_use]
102 pub fn full_name(&self) -> String {
103 match &self.parent {
104 Some(parent) => {
105 let mut name = parent.full_name();
106 name.push_str(JOIN);
107 name.push_str(self.name.as_str());
108 name
109 }
110 None => self.name.clone(),
111 }
112 }
113
114 #[must_use]
116 pub fn trace_enabled(&self) -> bool {
117 self.enabled_for(log::Level::Trace)
118 }
119
120 #[must_use]
123 pub fn enabled_for(&self, level: log::Level) -> bool {
124 level <= self.enabled_level
125 }
126
127 pub fn track_capacity(&self, value: usize, units: impl Into<String>) {
129 self.tracker.capacity(self.id, Capacity::new(value, units));
130 }
131
132 pub fn track_enter(&self, entered: Id) {
134 self.tracker.enter(self.id, entered);
135 }
136
137 pub fn track_exit(&self, exited: Id) {
139 self.tracker.exit(self.id, exited);
140 }
141
142 fn track_create(&self, created_by: Id, full_name: &str) {
143 self.tracker.create_entity(created_by, self.id, full_name);
144 }
145}
146
147impl Drop for Entity {
148 fn drop(&mut self) {
149 destroy!(self);
150 }
151}
152
153impl fmt::Debug for Entity {
154 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
155 f.debug_struct("Entity")
156 .field("name", &self.name)
157 .field("parent", &self.parent)
158 .field("id", &self.id)
159 .finish()
160 }
161}
162
163impl fmt::Display for Entity {
164 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165 if let Some(parent) = &self.parent {
166 parent.fmt(f).unwrap();
167 write!(f, "{}{}", JOIN, self.name)
168 } else {
169 write!(f, "{}", self.name)
170 }
171 }
172}
173
174pub fn toplevel(tracker: &Tracker, name: &str) -> Rc<Entity> {
177 let id = tracker.unique_id();
178 let enabled_level = tracker.add_entity(id, name, None);
179 let top = Rc::new(Entity {
180 parent: None,
181 name: String::from(name),
182 id,
183 tracker: tracker.clone(),
184 enabled_level,
185 });
186 top.track_create(crate::NO_ID, name);
187 top
188}
189
190pub struct EntityMonitor {
192 pub entity: Rc<Entity>,
194
195 pub id: Id,
197
198 pub name: String,
200}
201
202impl EntityMonitor {
203 #[must_use]
205 pub fn new(parent: &Rc<Entity>, name: &str) -> Self {
206 let mut full_name = parent.full_name();
207 full_name.push_str(JOIN);
208 full_name.push_str(name);
209
210 let id = create_id!(parent);
211 parent.tracker.add_entity(id, &full_name, None);
212
213 let monitor = Self {
214 entity: parent.clone(),
215 id,
216 name: String::from(name),
217 };
218
219 monitor.track_create(parent.id, &full_name);
220
221 monitor
222 }
223
224 fn track_create(&self, created_by: Id, full_name: &str) {
225 self.entity
226 .tracker
227 .create_monitor(created_by, self.id, full_name);
228 }
229
230 pub fn track_value(&self, value: f64) {
232 self.entity.tracker.value(self.entity.id, value);
233 }
234}
235
236pub struct EntityLane {
238 pub entity: Rc<Entity>,
240
241 pub id: Id,
243
244 pub name: String,
246
247 active: bool,
248 active_activity: Option<Id>,
249 active_group: Option<Id>,
250}
251
252impl EntityLane {
253 #[must_use]
255 pub fn new(parent: &Rc<Entity>, name: &str) -> Self {
256 let mut full_name = parent.full_name();
257 full_name.push_str(JOIN);
258 full_name.push_str(name);
259
260 let id = create_id!(parent);
261 let lane = Self {
262 entity: parent.clone(),
263 id,
264 name: String::from(name),
265 active: false,
266 active_activity: None,
267 active_group: None,
268 };
269
270 lane.track_create(parent.id, &full_name);
271
272 lane
273 }
274
275 fn track_create(&self, created_by: Id, full_name: &str) {
276 self.entity
277 .tracker
278 .create_lane(created_by, self.id, full_name);
279 }
280
281 pub fn begin(&mut self, name: &str) {
283 let activity_id = create_id!(self.entity);
284 self.entity
285 .tracker
286 .begin_activity(activity_id, self.id, name);
287 self.active_activity = Some(activity_id);
288 self.active = true;
289 }
290
291 pub fn begin_in_group(&mut self, name: &str, group: &EntityGroup) {
293 let activity_id = create_id!(self.entity);
294 self.entity.tracker.add_to_group(activity_id, group.id);
295 self.active_activity = Some(activity_id);
296 self.active_group = Some(group.id);
297 self.entity
298 .tracker
299 .begin_activity(activity_id, self.id, name);
300 self.active = true;
301 }
302
303 pub fn end(&mut self) {
305 if self.active {
306 let activity_id = self
307 .active_activity
308 .take()
309 .expect("active lane should have an activity ID");
310 self.entity.tracker.end_activity(activity_id);
311 if let Some(group_id) = self.active_group.take() {
312 self.entity.tracker.remove_from_group(activity_id, group_id);
313 }
314 self.active = false;
315 }
316 }
317}
318
319impl Drop for EntityLane {
320 fn drop(&mut self) {
321 self.end();
322 self.entity.tracker.destroy(self.entity.id, self.id);
323 }
324}
325
326pub struct EntityGroup {
328 pub entity: Rc<Entity>,
330
331 pub id: Id,
333
334 pub name: String,
336}
337
338impl EntityGroup {
339 #[must_use]
341 pub fn new(parent: &Rc<Entity>, name: &str) -> Self {
342 let mut full_name = parent.full_name();
343 full_name.push_str(JOIN);
344 full_name.push_str(name);
345
346 let id = create_id!(parent);
347 let group = Self {
348 entity: parent.clone(),
349 id,
350 name: String::from(name),
351 };
352
353 group
354 .entity
355 .tracker
356 .create_group(parent.id, group.id, &full_name);
357
358 group
359 }
360}
361
362impl Drop for EntityGroup {
363 fn drop(&mut self) {
364 self.entity.tracker.destroy(self.entity.id, self.id);
365 }
366}
367
368pub trait GetEntity {
370 fn entity(&self) -> &Rc<Entity>;
372}
373
374impl GetEntity for EntityMonitor {
375 fn entity(&self) -> &Rc<Entity> {
376 &self.entity
377 }
378}