Skip to main content

alopex_cli/output/
server.rs

1//! Server management output helpers.
2
3use crate::models::{Column, DataType, Row, Value};
4
5pub fn status_columns() -> Vec<Column> {
6    vec![
7        Column::new("Version", DataType::Text),
8        Column::new("Uptime (s)", DataType::Text),
9        Column::new("Connections", DataType::Text),
10        Column::new("QPS", DataType::Text),
11        Column::new("Cluster Schema", DataType::Text),
12        Column::new("Cluster Mode", DataType::Text),
13        Column::new("Node ID", DataType::Text),
14        Column::new("Lifecycle", DataType::Text),
15        Column::new("Degraded", DataType::Bool),
16        Column::new("Local Only", DataType::Bool),
17        Column::new("Future Distributed", DataType::Bool),
18        Column::new("Scatter/Gather", DataType::Bool),
19        Column::new("Diagnostics", DataType::Text),
20    ]
21}
22
23#[derive(Debug, Clone, Copy, Default)]
24pub struct StatusRowFields<'a> {
25    pub version: Option<&'a str>,
26    pub uptime_secs: Option<u64>,
27    pub connections: Option<u64>,
28    pub qps: Option<f64>,
29    pub cluster_schema_version: Option<u32>,
30    pub cluster_mode: Option<&'a str>,
31    pub node_id: Option<&'a str>,
32    pub lifecycle_state: Option<&'a str>,
33    pub degraded: Option<bool>,
34    pub local_only: Option<bool>,
35    pub future_distributed: Option<bool>,
36    pub scatter_gather: Option<bool>,
37    pub diagnostics: Option<&'a str>,
38}
39
40pub fn status_row(fields: StatusRowFields<'_>) -> Row {
41    Row::new(vec![
42        Value::Text(opt_text(fields.version)),
43        Value::Text(opt_u64(fields.uptime_secs)),
44        Value::Text(opt_u64(fields.connections)),
45        Value::Text(opt_f64(fields.qps)),
46        Value::Text(opt_u32(fields.cluster_schema_version)),
47        Value::Text(opt_text(fields.cluster_mode)),
48        Value::Text(opt_text(fields.node_id)),
49        Value::Text(opt_text(fields.lifecycle_state)),
50        opt_bool_value(fields.degraded),
51        opt_bool_value(fields.local_only),
52        opt_bool_value(fields.future_distributed),
53        opt_bool_value(fields.scatter_gather),
54        Value::Text(opt_text(fields.diagnostics)),
55    ])
56}
57
58pub fn metrics_columns() -> Vec<Column> {
59    vec![
60        Column::new("QPS", DataType::Text),
61        Column::new("Avg Latency (ms)", DataType::Text),
62        Column::new("P99 Latency (ms)", DataType::Text),
63        Column::new("Memory (MB)", DataType::Text),
64        Column::new("Active Connections", DataType::Text),
65    ]
66}
67
68pub fn metrics_row(
69    qps: Option<f64>,
70    avg_latency_ms: Option<f64>,
71    p99_latency_ms: Option<f64>,
72    memory_usage_mb: Option<u64>,
73    active_connections: Option<u64>,
74) -> Row {
75    Row::new(vec![
76        Value::Text(opt_f64(qps)),
77        Value::Text(opt_f64(avg_latency_ms)),
78        Value::Text(opt_f64(p99_latency_ms)),
79        Value::Text(opt_u64(memory_usage_mb)),
80        Value::Text(opt_u64(active_connections)),
81    ])
82}
83
84pub fn health_columns() -> Vec<Column> {
85    vec![
86        Column::new("Status", DataType::Text),
87        Column::new("Message", DataType::Text),
88        Column::new("Degraded", DataType::Bool),
89        Column::new("Cluster Mode", DataType::Text),
90        Column::new("Node ID", DataType::Text),
91    ]
92}
93
94pub fn health_row(
95    status: Option<&str>,
96    message: Option<&str>,
97    degraded: Option<bool>,
98    cluster_mode: Option<&str>,
99    node_id: Option<&str>,
100) -> Row {
101    Row::new(vec![
102        Value::Text(opt_text(status)),
103        Value::Text(opt_text(message)),
104        opt_bool_value(degraded),
105        Value::Text(opt_text(cluster_mode)),
106        Value::Text(opt_text(node_id)),
107    ])
108}
109
110pub fn compaction_columns() -> Vec<Column> {
111    vec![
112        Column::new("Status", DataType::Text),
113        Column::new("Message", DataType::Text),
114    ]
115}
116
117pub fn compaction_row(success: Option<bool>, message: Option<&str>) -> Row {
118    let result = match success {
119        Some(true) => "OK",
120        Some(false) => "Failed",
121        None => "N/A",
122    };
123    Row::new(vec![
124        Value::Text(result.to_string()),
125        Value::Text(opt_text(message)),
126    ])
127}
128
129pub fn cluster_operation_columns() -> Vec<Column> {
130    vec![
131        Column::new("Action", DataType::Text),
132        Column::new("Mode", DataType::Text),
133        Column::new("Node", DataType::Text),
134        Column::new("Lifecycle", DataType::Text),
135        Column::new("Degraded", DataType::Text),
136    ]
137}
138
139pub fn cluster_operation_row(
140    action: Option<&str>,
141    mode: Option<&str>,
142    node_id: Option<&str>,
143    lifecycle_state: Option<&str>,
144    degraded: Option<bool>,
145) -> Row {
146    Row::new(vec![
147        Value::Text(opt_text(action)),
148        Value::Text(opt_text(mode)),
149        Value::Text(opt_text(node_id)),
150        Value::Text(opt_text(lifecycle_state)),
151        Value::Text(opt_bool(degraded)),
152    ])
153}
154
155fn opt_text(value: Option<&str>) -> String {
156    value.unwrap_or("N/A").to_string()
157}
158
159fn opt_u64(value: Option<u64>) -> String {
160    value
161        .map(|value| value.to_string())
162        .unwrap_or_else(|| "N/A".to_string())
163}
164
165fn opt_u32(value: Option<u32>) -> String {
166    value
167        .map(|value| value.to_string())
168        .unwrap_or_else(|| "N/A".to_string())
169}
170
171fn opt_f64(value: Option<f64>) -> String {
172    value
173        .map(|value| format!("{:.2}", value))
174        .unwrap_or_else(|| "N/A".to_string())
175}
176
177fn opt_bool(value: Option<bool>) -> String {
178    value
179        .map(|value| value.to_string())
180        .unwrap_or_else(|| "N/A".to_string())
181}
182
183fn opt_bool_value(value: Option<bool>) -> Value {
184    value.map(Value::Bool).unwrap_or(Value::Null)
185}