use super::{exporters::MetricsExporter, Metrics};
pub struct StdoutMetricsExporter;
impl MetricsExporter for StdoutMetricsExporter {
fn export(&self, metrics: &Metrics) {
print_metrics(metrics);
}
}
impl StdoutMetricsExporter {
pub fn new() -> Box<dyn MetricsExporter> {
Box::new(StdoutMetricsExporter)
}
}
pub fn print_metrics(metrics: &Metrics) {
println!(
"[{}] │ METRICS │ {}.{} ({})",
chrono::Utc::now().format("%Y-%m-%dT%H:%M:%S%.3fZ"),
metrics.app_name,
metrics.service_name,
metrics.replica_id
);
println!("│ Interval │ {}s", metrics.interval_secs);
println!("├─────────────────────────────────────────────────────────────────────────────");
if let Some(ref system_metrics) = metrics.system_metrics {
println!("│ System Metrics");
println!("│ CPU Usage │ {:.2}%", system_metrics.cpu_usage);
println!(
"│ Memory │ {} / {} MB",
system_metrics.memory_used / 1_000_000,
system_metrics.memory_total / 1_000_000
);
println!(
"│ Swap │ {} / {} MB",
system_metrics.swap_used / 1_000_000,
system_metrics.swap_total / 1_000_000
);
println!(
"│ Disk Space │ {} / {} GB",
system_metrics.disk_available_space / 1_000_000_000,
system_metrics.disk_total_space / 1_000_000_000
);
println!("├─────────────────────────────────────────────────────────────────────────────");
}
if let Some(ref process_metrics) = metrics.process_metrics {
println!("│ Process Metrics");
println!("│ CPU Usage │ {:.2}%", process_metrics.cpu_usage);
println!(
"│ Memory Usage │ {} MB",
process_metrics.memory_usage / 1_000_000
);
println!(
"│ Disk Written │ {} MB",
process_metrics.disk_usage / 1_000_000
);
println!("├─────────────────────────────────────────────────────────────────────────────");
}
if let Some(ref http_metrics) = metrics.http_metrics {
println!("│ HTTP Metrics");
println!("│ Requests/min │ {}", http_metrics.requests_per_interval);
println!(
"│ Status Codes │ {:?}",
http_metrics.status_code_distribution
);
println!("│ Top Methods │ {:?}", http_metrics.method_count);
println!(
"│ Avg Duration │ {:?}",
http_metrics
.average_request_duration
.iter()
.map(|((method, status), &duration)| (
format!("{} {}", method, status),
duration as f64 / 1_000_000.0
))
.collect::<std::collections::HashMap<_, _>>()
);
println!("├─────────────────────────────────────────────────────────────────────────────");
}
if let Some(ref grpc_metrics) = metrics.grpc_metrics {
println!("│ gRPC Metrics");
println!("│ Calls/min │ {}", grpc_metrics.calls_per_interval);
println!(
"│ Status Codes │ {:?}",
grpc_metrics.status_code_distribution
);
println!("│ Top Services │ {:?}", grpc_metrics.service_count);
println!(
"│ Avg Duration │ {:?}",
grpc_metrics
.average_call_duration
.iter()
.map(|(service, &duration)| (service.clone(), duration as f64 / 1_000_000.0))
.collect::<std::collections::HashMap<_, _>>()
);
println!("├─────────────────────────────────────────────────────────────────────────────");
}
if let Some(ref websocket_metrics) = metrics.websocket_metrics {
println!("│ WebSocket Metrics");
println!("│ New connections │ {}", websocket_metrics.new_connections);
println!("│ Disconnections │ {}", websocket_metrics.disconnections);
println!("├─────────────────────────────────────────────────────────────────────────────");
}
println!("└─────────────────────────────────────────────────────────────────────────────");
}