wlan_telemetry/processors/
toggle_events.rs1use crate::util::cobalt_logger::log_cobalt_1dot1;
6use fuchsia_inspect::Node as InspectNode;
7use fuchsia_inspect_contrib::inspect_log;
8use fuchsia_inspect_contrib::nodes::BoundedListNode;
9use {fuchsia_async as fasync, wlan_legacy_metrics_registry as metrics};
10
11pub const INSPECT_TOGGLE_EVENTS_LIMIT: usize = 20;
12const TIME_QUICK_TOGGLE_WIFI: fasync::MonotonicDuration =
13 fasync::MonotonicDuration::from_seconds(5);
14
15#[derive(Debug, PartialEq)]
16pub enum ClientConnectionsToggleEvent {
17 Enabled,
18 Disabled,
19}
20
21pub struct ToggleLogger {
22 toggle_inspect_node: BoundedListNode,
23 cobalt_1dot1_proxy: fidl_fuchsia_metrics::MetricEventLoggerProxy,
24 current_state: Option<ClientConnectionsToggleEvent>,
27 time_stopped: Option<fasync::MonotonicInstant>,
30}
31
32impl ToggleLogger {
33 pub fn new(
34 cobalt_1dot1_proxy: fidl_fuchsia_metrics::MetricEventLoggerProxy,
35 inspect_node: &InspectNode,
36 ) -> Self {
37 let toggle_events = inspect_node.create_child("client_connections_toggle_events");
39 let toggle_inspect_node = BoundedListNode::new(toggle_events, INSPECT_TOGGLE_EVENTS_LIMIT);
40 let current_state = None;
41 let time_stopped = None;
42
43 Self { toggle_inspect_node, cobalt_1dot1_proxy, current_state, time_stopped }
44 }
45
46 pub async fn log_toggle_event(&mut self, event_type: ClientConnectionsToggleEvent) {
47 inspect_log!(self.toggle_inspect_node, {
49 event_type: std::format!("{:?}", event_type)
50 });
51
52 let curr_time = fasync::MonotonicInstant::now();
53 match &event_type {
54 ClientConnectionsToggleEvent::Enabled => {
55 if self.current_state == Some(ClientConnectionsToggleEvent::Disabled) {
58 if let Some(time_stopped) = self.time_stopped {
59 if curr_time - time_stopped < TIME_QUICK_TOGGLE_WIFI {
60 self.log_quick_toggle().await;
61 }
62 }
63 }
64 }
65 ClientConnectionsToggleEvent::Disabled => {
66 if self.current_state == Some(ClientConnectionsToggleEvent::Enabled) {
68 self.time_stopped = Some(curr_time);
69 }
70 }
71 }
72 self.current_state = Some(event_type);
73 }
74
75 async fn log_quick_toggle(&mut self) {
76 log_cobalt_1dot1!(
77 self.cobalt_1dot1_proxy,
78 log_occurrence,
79 metrics::CLIENT_CONNECTIONS_STOP_AND_START_METRIC_ID,
80 1,
81 &[],
82 );
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89 use crate::testing::{setup_test, TestHelper};
90 use diagnostics_assertions::{assert_data_tree, AnyNumericProperty};
91 use futures::task::Poll;
92 use std::pin::pin;
93 use wlan_common::assert_variant;
94
95 #[fuchsia::test]
96 fn test_toggle_is_recorded_to_inspect() {
97 let mut test_helper = setup_test();
98 let node = test_helper.create_inspect_node("wlan_mock_node");
99 let mut toggle_logger = ToggleLogger::new(test_helper.cobalt_1dot1_proxy.clone(), &node);
100
101 let event = ClientConnectionsToggleEvent::Enabled;
102 run_log_toggle_event(&mut test_helper, &mut toggle_logger, event);
103
104 let event = ClientConnectionsToggleEvent::Disabled;
105 run_log_toggle_event(&mut test_helper, &mut toggle_logger, event);
106
107 let event = ClientConnectionsToggleEvent::Enabled;
108 run_log_toggle_event(&mut test_helper, &mut toggle_logger, event);
109
110 assert_data_tree!(test_helper.inspector, root: contains {
111 wlan_mock_node: {
112 client_connections_toggle_events: {
113 "0": {
114 "event_type": "Enabled",
115 "@time": AnyNumericProperty
116 },
117 "1": {
118 "event_type": "Disabled",
119 "@time": AnyNumericProperty
120 },
121 "2": {
122 "event_type": "Enabled",
123 "@time": AnyNumericProperty
124 },
125 }
126 }
127 });
128 }
129
130 fn run_log_toggle_event(
133 test_helper: &mut TestHelper,
134 toggle_logger: &mut ToggleLogger,
135 event: ClientConnectionsToggleEvent,
136 ) {
137 let mut test_fut = pin!(toggle_logger.log_toggle_event(event));
138 assert_eq!(
139 test_helper.run_until_stalled_drain_cobalt_events(&mut test_fut),
140 Poll::Ready(())
141 );
142 }
143
144 #[fuchsia::test]
145 fn test_quick_toggle_metric_is_recorded() {
146 let mut test_helper = setup_test();
147 let inspect_node = test_helper.create_inspect_node("test_stats");
148 let mut toggle_logger =
149 ToggleLogger::new(test_helper.cobalt_1dot1_proxy.clone(), &inspect_node);
150
151 let mut test_time = fasync::MonotonicInstant::from_nanos(123);
153 let event = ClientConnectionsToggleEvent::Enabled;
154 run_log_toggle_event(&mut test_helper, &mut toggle_logger, event);
155
156 test_time += fasync::MonotonicDuration::from_minutes(40);
158 test_helper.exec.set_fake_time(test_time);
159 let event = ClientConnectionsToggleEvent::Disabled;
160 run_log_toggle_event(&mut test_helper, &mut toggle_logger, event);
161
162 test_time += fasync::MonotonicDuration::from_seconds(1);
163 test_helper.exec.set_fake_time(test_time);
164 let event = ClientConnectionsToggleEvent::Enabled;
165 run_log_toggle_event(&mut test_helper, &mut toggle_logger, event);
166
167 let logged_metrics =
169 test_helper.get_logged_metrics(metrics::CLIENT_CONNECTIONS_STOP_AND_START_METRIC_ID);
170 assert_variant!(&logged_metrics[..], [metric] => {
171 let expected_metric = fidl_fuchsia_metrics::MetricEvent {
172 metric_id: metrics::CLIENT_CONNECTIONS_STOP_AND_START_METRIC_ID,
173 event_codes: vec![],
174 payload: fidl_fuchsia_metrics::MetricEventPayload::Count(1),
175 };
176 assert_eq!(metric, &expected_metric);
177 });
178 }
179
180 #[fuchsia::test]
181 fn test_quick_toggle_no_metric_is_recorded_if_not_quick() {
182 let mut test_helper = setup_test();
183 let inspect_node = test_helper.create_inspect_node("test_stats");
184 let mut toggle_logger =
185 ToggleLogger::new(test_helper.cobalt_1dot1_proxy.clone(), &inspect_node);
186
187 let mut test_time = fasync::MonotonicInstant::from_nanos(123);
189 let event = ClientConnectionsToggleEvent::Enabled;
190 run_log_toggle_event(&mut test_helper, &mut toggle_logger, event);
191
192 test_time += fasync::MonotonicDuration::from_minutes(20);
194 test_helper.exec.set_fake_time(test_time);
195 let event = ClientConnectionsToggleEvent::Disabled;
196 run_log_toggle_event(&mut test_helper, &mut toggle_logger, event);
197
198 test_time += fasync::MonotonicDuration::from_minutes(30);
199 test_helper.exec.set_fake_time(test_time);
200 let event = ClientConnectionsToggleEvent::Enabled;
201 run_log_toggle_event(&mut test_helper, &mut toggle_logger, event);
202
203 let logged_metrics =
206 test_helper.get_logged_metrics(metrics::CLIENT_CONNECTIONS_STOP_AND_START_METRIC_ID);
207 assert!(logged_metrics.is_empty());
208 }
209
210 #[fuchsia::test]
211 fn test_quick_toggle_metric_second_disable_doesnt_update_time() {
212 let mut test_helper = setup_test();
215 let inspect_node = test_helper.create_inspect_node("test_stats");
216 let mut toggle_logger =
217 ToggleLogger::new(test_helper.cobalt_1dot1_proxy.clone(), &inspect_node);
218
219 let mut test_time = fasync::MonotonicInstant::from_nanos(123);
221 let event = ClientConnectionsToggleEvent::Enabled;
222 run_log_toggle_event(&mut test_helper, &mut toggle_logger, event);
223
224 test_time += fasync::MonotonicDuration::from_minutes(40);
226 test_helper.exec.set_fake_time(test_time);
227 let event = ClientConnectionsToggleEvent::Disabled;
228 run_log_toggle_event(&mut test_helper, &mut toggle_logger, event);
229
230 test_time += fasync::MonotonicDuration::from_minutes(30);
231 test_helper.exec.set_fake_time(test_time);
232 let event = ClientConnectionsToggleEvent::Disabled;
233 run_log_toggle_event(&mut test_helper, &mut toggle_logger, event);
234
235 test_time += fasync::MonotonicDuration::from_seconds(1);
237 test_helper.exec.set_fake_time(test_time);
238 let event = ClientConnectionsToggleEvent::Enabled;
239 run_log_toggle_event(&mut test_helper, &mut toggle_logger, event);
240
241 let logged_metrics =
244 test_helper.get_logged_metrics(metrics::CLIENT_CONNECTIONS_STOP_AND_START_METRIC_ID);
245 assert!(logged_metrics.is_empty());
246 }
247}