iggy_cli/commands/binary_system/
stats.rs1use crate::commands::cli_command::{CliCommand, PRINT_TARGET};
20use anyhow::Context;
21use async_trait::async_trait;
22use comfy_table::Table;
23use iggy_common::Client;
24use std::fmt::Display;
25use std::time::SystemTime;
26use tracing::{Level, event};
27
28#[derive(Debug, Clone, Copy, Eq, PartialEq)]
29pub enum GetStatsOutput {
30 Table,
31 List,
32 Json,
33 Toml,
34}
35
36impl Display for GetStatsOutput {
37 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38 match self {
39 GetStatsOutput::Table => write!(f, "table"),
40 GetStatsOutput::List => write!(f, "list"),
41 GetStatsOutput::Json => write!(f, "json"),
42 GetStatsOutput::Toml => write!(f, "toml"),
43 }
44 }
45}
46
47pub struct GetStatsCmd {
48 quiet_mode: bool,
49 output: GetStatsOutput,
50}
51
52impl GetStatsCmd {
53 pub fn new(quiet_mode: bool, output: GetStatsOutput) -> Self {
54 Self { quiet_mode, output }
55 }
56}
57
58#[async_trait]
59impl CliCommand for GetStatsCmd {
60 fn explain(&self) -> String {
61 "stats command".to_owned()
62 }
63
64 async fn execute_cmd(&mut self, client: &dyn Client) -> anyhow::Result<(), anyhow::Error> {
65 let stats = client
66 .get_stats()
67 .await
68 .with_context(|| "Problem sending get_stats command".to_owned())?;
69
70 let output = match self.output {
71 GetStatsOutput::Table => {
72 let mut table = Table::new();
73
74 table.set_header(vec!["Server property", "Value"]);
75 table.add_row(vec![
76 "Iggy Server PID",
77 format!("{}", stats.process_id).as_str(),
78 ]);
79 table.add_row(vec![
80 "Iggy Server CPU Usage",
81 format!("{:.4} %", stats.cpu_usage).as_str(),
82 ]);
83 table.add_row(vec![
84 "Total CPU Usage",
85 format!("{:.4} %", stats.total_cpu_usage).as_str(),
86 ]);
87 table.add_row(vec![
88 "Iggy Server Memory Usage",
89 stats.memory_usage.as_bytes_u64().to_string().as_str(),
90 ]);
91
92 table.add_row(vec![
93 "Total Memory (RAM)",
94 stats.total_memory.as_bytes_u64().to_string().as_str(),
95 ]);
96 table.add_row(vec![
97 "Available Memory (RAM)",
98 stats.available_memory.as_bytes_u64().to_string().as_str(),
99 ]);
100 table.add_row(vec![
101 "Iggy Server Run Time",
102 stats.run_time.as_secs().to_string().as_str(),
103 ]);
104
105 let start_time_utc = stats.start_time + SystemTime::UNIX_EPOCH;
106 table.add_row(vec![
107 "Start Time (UTC)",
108 start_time_utc.to_string().as_str(),
109 ]);
110
111 table.add_row(vec![
112 "Read Bytes",
113 stats.read_bytes.as_bytes_u64().to_string().as_str(),
114 ]);
115 table.add_row(vec![
116 "Written Bytes",
117 stats.written_bytes.as_bytes_u64().to_string().as_str(),
118 ]);
119 table.add_row(vec![
120 "Messages Size Bytes",
121 stats
122 .messages_size_bytes
123 .as_bytes_u64()
124 .to_string()
125 .as_str(),
126 ]);
127 table.add_row(vec![
128 "Streams Count",
129 format!("{}", stats.streams_count).as_str(),
130 ]);
131 table.add_row(vec![
132 "Topics Count",
133 format!("{}", stats.topics_count).as_str(),
134 ]);
135 table.add_row(vec![
136 "Partitions Count",
137 format!("{}", stats.partitions_count).as_str(),
138 ]);
139 table.add_row(vec![
140 "Segments Count",
141 format!("{}", stats.segments_count).as_str(),
142 ]);
143 table.add_row(vec![
144 "Message Count",
145 format!("{}", stats.messages_count).as_str(),
146 ]);
147 table.add_row(vec![
148 "Clients Count",
149 format!("{}", stats.clients_count).as_str(),
150 ]);
151 table.add_row(vec![
152 "Consumer Groups Count",
153 format!("{}", stats.consumer_groups_count).as_str(),
154 ]);
155
156 table.add_row(vec![
157 "Threads Count",
158 format!("{}", stats.threads_count).as_str(),
159 ]);
160 table.add_row(vec![
161 "Free Disk Space",
162 stats.free_disk_space.as_bytes_u64().to_string().as_str(),
163 ]);
164 table.add_row(vec![
165 "Total Disk Space",
166 stats.total_disk_space.as_bytes_u64().to_string().as_str(),
167 ]);
168
169 table.add_row(vec!["OS Name", stats.os_name.as_str()]);
170 table.add_row(vec!["OS Version", stats.os_version.as_str()]);
171 table.add_row(vec!["Kernel Version", stats.kernel_version.as_str()]);
172
173 table.to_string()
174 }
175 GetStatsOutput::List => {
176 let mut list = Vec::new();
177
178 list.push(format!("Iggy Server PID|{}", stats.process_id));
179 list.push(format!("Iggy Server CPU Usage|{:.4} %", stats.cpu_usage));
180 list.push(format!("Total CPU Usage|{:.4} %", stats.total_cpu_usage));
181 list.push(format!(
182 "Iggy Server Memory Usage|{}",
183 stats.memory_usage.as_bytes_u64()
184 ));
185 list.push(format!(
186 "Total Memory (RAM)|{}",
187 stats.total_memory.as_bytes_u64()
188 ));
189 list.push(format!(
190 "Available Memory (RAM)|{}",
191 stats.available_memory.as_bytes_u64()
192 ));
193 list.push(format!("Iggy Server Run Time|{}", stats.run_time.as_secs()));
194
195 let start_time_utc = stats.start_time + SystemTime::UNIX_EPOCH;
196 list.push(format!("Start Time (UTC)|{start_time_utc}"));
197
198 list.push(format!("Read Bytes|{}", stats.read_bytes.as_bytes_u64()));
199 list.push(format!(
200 "Written Bytes|{}",
201 stats.written_bytes.as_bytes_u64()
202 ));
203 list.push(format!(
204 "Messages Size Bytes|{}",
205 stats.messages_size_bytes.as_bytes_u64()
206 ));
207 list.push(format!("Streams Count|{}", stats.streams_count));
208 list.push(format!("Topics Count|{}", stats.topics_count));
209 list.push(format!("Partitions Count|{}", stats.partitions_count));
210 list.push(format!("Segments Count|{}", stats.segments_count));
211 list.push(format!("Message Count|{}", stats.messages_count));
212 list.push(format!("Clients Count|{}", stats.clients_count));
213 list.push(format!(
214 "Consumer Groups Count|{}",
215 stats.consumer_groups_count
216 ));
217
218 list.push(format!("Threads Count|{}", stats.threads_count));
219 list.push(format!(
220 "Free Disk Space|{}",
221 stats.free_disk_space.as_bytes_u64()
222 ));
223 list.push(format!(
224 "Total Disk Space|{}",
225 stats.total_disk_space.as_bytes_u64()
226 ));
227
228 list.push(format!("OS Name|{}", stats.os_name));
229 list.push(format!("OS Version|{}", stats.os_version));
230 list.push(format!("Kernel Version|{}", stats.kernel_version));
231
232 list.join("\n")
233 }
234 GetStatsOutput::Toml => toml::to_string(&stats)?,
235 GetStatsOutput::Json => serde_json::to_string_pretty(&stats)?,
236 };
237
238 if self.quiet_mode {
239 println!("{output}");
240 } else {
241 event!(target: PRINT_TARGET, Level::INFO,"{output}");
242 }
243
244 Ok(())
245 }
246}