rustmeter_beacon_target/
monitors.rs1use crate::numeric_registry::NumericRegistry;
2
3pub static VALUE_MONITOR_REGISTRY: NumericRegistry = NumericRegistry::new();
4pub static CODE_MONITOR_REGISTRY: NumericRegistry = NumericRegistry::new();
5
6#[macro_export]
7macro_rules! get_static_id_by_registry {
8 ($registry:expr) => {{
9 use rustmeter_beacon::_private::portable_atomic::{AtomicUsize, Ordering};
10 static LOCAL_MONITOR_VALUE_ID: AtomicUsize = AtomicUsize::new(0);
11
12 match LOCAL_MONITOR_VALUE_ID.load(Ordering::Relaxed) {
14 0 => {
15 let id = VALUE_MONITOR_REGISTRY.allocate_new_id();
17 let res = LOCAL_MONITOR_VALUE_ID.compare_exchange(
18 0,
19 id,
20 Ordering::Relaxed,
21 Ordering::Relaxed,
22 );
23
24 match res {
25 Ok(_) => {
26 (id, true)
28 }
29 Err(actual) => {
30 (actual, false)
32 }
33 }
34 }
35 id => (id, false),
36 }
37 }};
38}
39
40#[allow(unused_variables)]
41pub fn defmt_trace_new_monitored_value(name: &str, local_id: usize) {
42 #[cfg(feature = "defmt")]
43 defmt::trace!(
44 "Registered new monitored value: {} with id {}",
45 name,
46 local_id
47 );
48}
49
50#[macro_export]
51macro_rules! monitor_value {
64 ($name:literal, $val:expr) => {
65 const _: () = {
69 core::assert!($name.len() <= 20, "Name of value to be monitored must be 20 characters or less");
70 };
71
72 use crate::monitors::{CODE_MONITOR_REGISTRY, VALUE_MONITOR_REGISTRY};
73 use rustmeter_beacon::protocol::MonitorValuePayload;
74
75 let (local_id, registered_newly) = get_static_id_by_registry!(VALUE_MONITOR_REGISTRY);
76
77 if registered_newly {
79 let payload = rustmeter_beacon::protocol::TypeDefinitionPayload::ValueMonitor {
80 value_id: local_id as u8,
81 name: $name,
82 };
83 rustmeter_beacon::tracing::write_tracing_event(rustmeter_beacon::protocol::EventPayload::TypeDefinition(payload));
84
85 rustmeter_beacon::monitors::defmt_trace_new_monitored_value($name, local_id);
86 }
87
88 rustmeter_beacon::tracing::write_tracing_event(rustmeter_beacon::protocol::EventPayload::MonitorValue {
90 value_id: local_id as u8,
91 value: $val.into(),
92 });
93 };
94}
95
96pub struct DropGuard<F: FnOnce()> {
98 drop_fn: Option<F>,
99}
100
101impl<F: FnOnce()> DropGuard<F> {
102 pub fn new(drop_fn: F) -> Self {
103 Self {
104 drop_fn: Some(drop_fn),
105 }
106 }
107}
108
109impl<F: FnOnce()> Drop for DropGuard<F> {
110 fn drop(&mut self) {
111 if let Some(f) = self.drop_fn.take() {
112 f();
113 }
114 }
115}
116
117#[allow(unused_variables)]
118pub fn defmt_trace_new_scope(name: &str, local_id: usize) {
119 #[cfg(feature = "defmt")]
120 defmt::trace!(
121 "Registered new scope monitor: {} with id {}",
122 name,
123 local_id
124 );
125}
126
127#[macro_export]
128macro_rules! monitor_scoped {
146 ($name:literal, $body:block) => {{
147 const _: () = {
149 core::assert!($name.len() <= 20, "Scope name must be 20 characters or less");
150 };
151
152 use rustmeter_beacon::monitors::{CODE_MONITOR_REGISTRY, VALUE_MONITOR_REGISTRY};
153 use rustmeter_beacon::get_static_id_by_registry;
154 use rustmeter_beacon::tracing::write_tracing_event;
155
156 let (local_id, registered_newly) = get_static_id_by_registry!(CODE_MONITOR_REGISTRY);
157
158 if registered_newly {
160 let payload = rustmeter_beacon::protocol::TypeDefinitionPayload::ScopeMonitor {
161 monitor_id: local_id as u8,
162 name: $name,
163 };
164 write_tracing_event(rustmeter_beacon::protocol::EventPayload::TypeDefinition(payload));
165
166 rustmeter_beacon::monitors::defmt_trace_new_scope($name, local_id);
167 }
168
169 let _guard = rustmeter_beacon::monitors::DropGuard::new(|| {
171 rustmeter_beacon::protocol::raw_writers::write_monitor_end();
172 });
173
174 rustmeter_beacon::protocol::raw_writers::write_monitor_start(local_id as u8);
176
177 { $body }
178 }};
179}
180
181#[allow(unused_variables)]
183pub fn defmt_trace_new_function_monitor(name: &str, local_id: usize) {
184 #[cfg(feature = "defmt")]
185 defmt::trace!(
186 "Registered new function monitor: {} with id {}",
187 name,
188 local_id
189 );
190}