channels_console/
channels_guard.rs

1use std::time::Instant;
2
3use prettytable::{Cell, Row, Table};
4
5use crate::{format_bytes, get_channel_stats, get_serializable_stats, resolve_label, Format};
6
7/// Builder for creating a ChannelsGuard with custom configuration.
8///
9/// # Examples
10///
11/// ```no_run
12/// use channels_console::{ChannelsGuardBuilder, Format};
13///
14/// let _guard = ChannelsGuardBuilder::new()
15///     .format(Format::JsonPretty)
16///     .build();
17/// // Statistics will be printed as pretty JSON when _guard is dropped
18/// ```
19pub struct ChannelsGuardBuilder {
20    format: Format,
21}
22
23impl ChannelsGuardBuilder {
24    /// Create a new channels guard builder.
25    pub fn new() -> Self {
26        Self {
27            format: Format::default(),
28        }
29    }
30
31    /// Set the output format for statistics.
32    ///
33    /// # Examples
34    ///
35    /// ```no_run
36    /// use channels_console::{ChannelsGuardBuilder, Format};
37    ///
38    /// let _guard = ChannelsGuardBuilder::new()
39    ///     .format(Format::Json)
40    ///     .build();
41    /// ```
42    pub fn format(mut self, format: Format) -> Self {
43        self.format = format;
44        self
45    }
46
47    /// Build and return the ChannelsGuard.
48    /// Statistics will be printed when the guard is dropped.
49    pub fn build(self) -> ChannelsGuard {
50        ChannelsGuard {
51            start_time: Instant::now(),
52            format: self.format,
53        }
54    }
55}
56
57impl Default for ChannelsGuardBuilder {
58    fn default() -> Self {
59        Self::new()
60    }
61}
62
63/// Guard for channel statistics collection.
64/// When dropped, prints a summary of all instrumented channels and their statistics.
65///
66/// Use `ChannelsGuardBuilder` to create a guard with custom configuration.
67///
68/// # Examples
69///
70/// ```no_run
71/// use channels_console::ChannelsGuard;
72///
73/// let _guard = ChannelsGuard::new();
74/// // Your code with instrumented channels here
75/// // Statistics will be printed when _guard is dropped
76/// ```
77pub struct ChannelsGuard {
78    start_time: Instant,
79    format: Format,
80}
81
82impl ChannelsGuard {
83    /// Create a new channels guard with default settings (table format).
84    /// Statistics will be printed when this guard is dropped.
85    ///
86    /// For custom configuration, use `ChannelsGuardBuilder::new()` instead.
87    pub fn new() -> Self {
88        Self {
89            start_time: Instant::now(),
90            format: Format::default(),
91        }
92    }
93
94    /// Set the output format for statistics.
95    /// This is a convenience method for backward compatibility.
96    ///
97    /// # Examples
98    ///
99    /// ```no_run
100    /// use channels_console::{ChannelsGuard, Format};
101    ///
102    /// let _guard = ChannelsGuard::new().format(Format::Json);
103    /// ```
104    pub fn format(mut self, format: Format) -> Self {
105        self.format = format;
106        self
107    }
108}
109
110impl Default for ChannelsGuard {
111    fn default() -> Self {
112        Self::new()
113    }
114}
115
116impl Drop for ChannelsGuard {
117    fn drop(&mut self) {
118        let elapsed = self.start_time.elapsed();
119        let stats = get_channel_stats();
120
121        if stats.is_empty() {
122            println!("\nNo instrumented channels found.");
123            return;
124        }
125
126        match self.format {
127            Format::Table => {
128                let mut table = Table::new();
129
130                table.add_row(Row::new(vec![
131                    Cell::new("Channel"),
132                    Cell::new("Type"),
133                    Cell::new("State"),
134                    Cell::new("Sent"),
135                    Cell::new("Mem"),
136                    Cell::new("Received"),
137                    Cell::new("Queued"),
138                    Cell::new("Mem"),
139                ]));
140
141                let mut sorted_stats: Vec<_> = stats.into_iter().collect();
142                sorted_stats.sort_by(|a, b| {
143                    let la = resolve_label(a.1.id, a.1.label);
144                    let lb = resolve_label(b.1.id, b.1.label);
145                    la.cmp(&lb)
146                });
147
148                for (_key, channel_stats) in sorted_stats {
149                    let label = resolve_label(channel_stats.id, channel_stats.label);
150                    table.add_row(Row::new(vec![
151                        Cell::new(&label),
152                        Cell::new(&channel_stats.channel_type.to_string()),
153                        Cell::new(channel_stats.state.as_str()),
154                        Cell::new(&channel_stats.sent_count.to_string()),
155                        Cell::new(&format_bytes(channel_stats.total_bytes())),
156                        Cell::new(&channel_stats.received_count.to_string()),
157                        Cell::new(&channel_stats.queued().to_string()),
158                        Cell::new(&format_bytes(channel_stats.queued_bytes())),
159                    ]));
160                }
161
162                println!(
163                    "\n=== Channel Statistics (runtime: {:.2}s) ===",
164                    elapsed.as_secs_f64()
165                );
166                table.printstd();
167            }
168            Format::Json => {
169                let serializable_stats = get_serializable_stats();
170                match serde_json::to_string(&serializable_stats) {
171                    Ok(json) => println!("{}", json),
172                    Err(e) => eprintln!("Failed to serialize statistics to JSON: {}", e),
173                }
174            }
175            Format::JsonPretty => {
176                let serializable_stats = get_serializable_stats();
177                match serde_json::to_string_pretty(&serializable_stats) {
178                    Ok(json) => println!("{}", json),
179                    Err(e) => eprintln!("Failed to serialize statistics to pretty JSON: {}", e),
180                }
181            }
182        }
183    }
184}