Skip to main content

iggy_cli/commands/binary_system/
stats.rs

1/* Licensed to the Apache Software Foundation (ASF) under one
2 * or more contributor license agreements.  See the NOTICE file
3 * distributed with this work for additional information
4 * regarding copyright ownership.  The ASF licenses this file
5 * to you under the Apache License, Version 2.0 (the
6 * "License"); you may not use this file except in compliance
7 * with the License.  You may obtain a copy of the License at
8 *
9 *   http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing,
12 * software distributed under the License is distributed on an
13 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 * KIND, either express or implied.  See the License for the
15 * specific language governing permissions and limitations
16 * under the License.
17 */
18
19use 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}