1use crate::Id;
4use crate::entity::Capacity;
5use crate::tracker::aka::AlternativeNames;
6use crate::tracker::{EntityManager, Track, Tracker};
7
8pub struct MultiTracker {
10 entity_manager: EntityManager,
11 trackers: Vec<Tracker>,
12}
13
14impl MultiTracker {
15 pub fn add_tracker(&mut self, tracker: Tracker) {
18 self.trackers.push(tracker);
19 }
20}
21
22impl Default for MultiTracker {
23 fn default() -> Self {
24 Self {
25 entity_manager: EntityManager::new(log::Level::Error),
27 trackers: Vec::new(),
28 }
29 }
30}
31
32impl Track for MultiTracker {
33 fn unique_id(&self) -> Id {
34 self.entity_manager.unique_id()
35 }
36
37 fn enabled_level(&self, id: Id) -> log::Level {
38 self.trackers
39 .iter()
40 .map(|tracker| tracker.enabled_level(id))
41 .max()
42 .unwrap_or(log::Level::Error)
43 }
44
45 fn monitoring_window_size_for(&self, id: Id) -> Option<u64> {
46 for tracker in &self.trackers {
47 if let Some(window_size_ticks) = tracker.monitoring_window_size_for(id) {
48 return Some(window_size_ticks);
49 }
50 }
51 None
52 }
53
54 fn add_entity(
55 &self,
56 id: Id,
57 entity_name: &str,
58 alternative_names: AlternativeNames,
59 ) -> log::Level {
60 self.trackers
61 .iter()
62 .map(|tracker| tracker.add_entity(id, entity_name, alternative_names))
63 .max()
64 .unwrap_or(log::Level::Error)
65 }
66
67 fn enter(&self, id: Id, object: Id) {
68 for tracker in &self.trackers {
69 tracker.enter(id, object);
70 }
71 }
72
73 fn exit(&self, id: Id, object: Id) {
74 for tracker in &self.trackers {
75 tracker.exit(id, object);
76 }
77 }
78
79 fn value(&self, id: Id, value: f64) {
80 for tracker in &self.trackers {
81 tracker.value(id, value);
82 }
83 }
84
85 fn begin_activity(&self, activity: Id, lane: Id, name: &str) {
86 for tracker in &self.trackers {
87 tracker.begin_activity(activity, lane, name);
88 }
89 }
90
91 fn add_to_group(&self, activity: Id, group_id: Id) {
92 for tracker in &self.trackers {
93 tracker.add_to_group(activity, group_id);
94 }
95 }
96
97 fn remove_from_group(&self, activity: Id, group_id: Id) {
98 for tracker in &self.trackers {
99 tracker.remove_from_group(activity, group_id);
100 }
101 }
102
103 fn end_activity(&self, activity: Id) {
104 for tracker in &self.trackers {
105 tracker.end_activity(activity);
106 }
107 }
108
109 fn create_entity(&self, created_by: Id, id: Id, name: &str) {
110 for tracker in &self.trackers {
111 tracker.create_entity(created_by, id, name);
112 }
113 }
114
115 fn create_monitor(&self, created_by: Id, id: Id, name: &str) {
116 for tracker in &self.trackers {
117 tracker.create_monitor(created_by, id, name);
118 }
119 }
120
121 fn create_lane(&self, created_by: Id, id: Id, name: &str) {
122 for tracker in &self.trackers {
123 tracker.create_lane(created_by, id, name);
124 }
125 }
126
127 fn create_group(&self, created_by: Id, id: Id, name: &str) {
128 for tracker in &self.trackers {
129 tracker.create_group(created_by, id, name);
130 }
131 }
132
133 fn create_object(
134 &self,
135 created_by: Id,
136 id: Id,
137 size: usize,
138 units: &str,
139 req_type: u8,
140 details: &str,
141 ) {
142 for tracker in &self.trackers {
143 tracker.create_object(created_by, id, size, units, req_type, details);
144 }
145 }
146
147 fn capacity(&self, id: Id, capacity: Capacity) {
148 for tracker in &self.trackers {
149 tracker.capacity(id, capacity.clone());
150 }
151 }
152
153 fn destroy(&self, destroyed_by: Id, id: Id) {
154 for tracker in &self.trackers {
155 tracker.destroy(destroyed_by, id);
156 }
157 }
158
159 fn connect(&self, connect_from: Id, connect_to: Id) {
160 for tracker in &self.trackers {
161 tracker.connect(connect_from, connect_to);
162 }
163 }
164
165 fn log(&self, id: Id, level: log::Level, msg: std::fmt::Arguments) {
166 for tracker in &self.trackers {
167 tracker.log(id, level, msg);
168 }
169 }
170
171 fn time(&self, set_by: Id, time_ns: f64) {
172 for tracker in &self.trackers {
173 tracker.time(set_by, time_ns);
174 }
175 }
176
177 fn shutdown(&self) {
178 for tracker in &self.trackers {
179 tracker.shutdown();
180 }
181 }
182}
183
184#[cfg(test)]
185mod tests {
186 use std::rc::Rc;
187
188 use log::Level;
189
190 use super::MultiTracker;
191 use crate::Id;
192 use crate::test_helpers::{TestTracker, check_and_clear};
193 use crate::tracker::{Track, Tracker};
194
195 #[test]
196 fn log_events_are_delivered_to_all_sub_trackers_even_if_only_one_enables_the_level() {
197 let trace_tracker = Rc::new(TestTracker::new(100, Level::Trace));
198 let error_tracker = Rc::new(TestTracker::new(200, Level::Error));
199
200 let mut multi_tracker = MultiTracker::default();
201 let trace_tracker_dyn: Tracker = trace_tracker.clone();
202 let error_tracker_dyn: Tracker = error_tracker.clone();
203 multi_tracker.add_tracker(trace_tracker_dyn);
204 multi_tracker.add_tracker(error_tracker_dyn);
205
206 let entity_id = Id(42);
207 assert!(multi_tracker.is_entity_enabled(entity_id, Level::Trace));
208
209 multi_tracker.log(entity_id, Level::Trace, format_args!("fanout"));
210
211 check_and_clear(&trace_tracker, &["42:TRACE: fanout"]);
212 check_and_clear(&error_tracker, &["42:TRACE: fanout"]);
213 }
214}