1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
45use crate::base::SettingType;
6use fuchsia_inspect::{self as inspect, component, NumericProperty};
7use fuchsia_inspect_derive::Inspect;
8use settings_inspect_utils::managed_inspect_map::ManagedInspectMap;
910const LISTENER_INSPECT_NODE_NAME: &str = "active_listeners";
1112pub struct ListenerInspectLogger {
13/// The saved information about each setting type's active listeners.
14listener_counts: ManagedInspectMap<ListenerInspectInfo>,
15}
1617impl Default for ListenerInspectLogger {
18fn default() -> Self {
19Self::new()
20 }
21}
2223/// Information about active listeners to be written to inspect.
24///
25/// Inspect nodes are not used, but need to be held as they're deleted from inspect once they go
26/// out of scope.
27#[derive(Default, Inspect)]
28struct ListenerInspectInfo {
29/// Node of this info.
30inspect_node: inspect::Node,
3132/// Number of active listeners.
33count: inspect::UintProperty,
34}
3536impl ListenerInspectLogger {
37/// Creates a new [ListenerInspectLogger] that writes to the default
38 /// [fuchsia_inspect::component::inspector()].
39pub fn new() -> Self {
40Self::with_inspector(component::inspector())
41 }
4243pub fn with_inspector(inspector: &inspect::Inspector) -> Self {
44let listener_counts_node = inspector.root().create_child(LISTENER_INSPECT_NODE_NAME);
45Self {
46 listener_counts: ManagedInspectMap::<ListenerInspectInfo>::with_node(
47 listener_counts_node,
48 ),
49 }
50 }
5152/// Adds a listener to the count for [setting_type].
53pub fn add_listener(&mut self, setting_type: SettingType) {
54let setting_type_str = format!("{setting_type:?}");
55let inspect_info =
56self.listener_counts.get_or_insert_with(setting_type_str, ListenerInspectInfo::default);
57let _ = inspect_info.count.add(1u64);
58 }
5960/// Removes a listener from the count for [setting_type].
61pub fn remove_listener(&mut self, setting_type: SettingType) {
62let setting_type_str = format!("{setting_type:?}");
63match self.listener_counts.map_mut().get_mut(&setting_type_str) {
64Some(listener_inspect_info) => {
65let _ = listener_inspect_info.count.subtract(1u64);
66 }
67None => log::error!("Tried to subtract from nonexistent listener count"),
68 }
69 }
70}
7172#[cfg(test)]
73mod tests {
74use super::*;
75use diagnostics_assertions::assert_data_tree;
7677#[fuchsia::test]
78fn test_listener_logger() {
79let inspector = inspect::Inspector::default();
8081let mut logger = ListenerInspectLogger::with_inspector(&inspector);
8283 logger.add_listener(SettingType::Unknown);
84 logger.add_listener(SettingType::Unknown);
85 logger.add_listener(SettingType::Unknown);
8687 logger.remove_listener(SettingType::Unknown);
8889// Since listeners were added thrice and removed once, the count at the end is 2.
90assert_data_tree!(inspector, root: {
91 active_listeners: {
92 Unknown: {
93"count": 2u64,
94 }
95 }
96 });
97 }
98}