feat: add metrics export as CSV/JSON (MON-04)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-11 12:33:19 +00:00
parent 1b8a8cfd32
commit 980fc3af6d
4 changed files with 116 additions and 3 deletions

View File

@@ -440,6 +440,7 @@ impl RpcHandler {
"monitoring.alert-rules" => self.handle_monitoring_alert_rules().await,
"monitoring.configure-alert" => self.handle_monitoring_configure_alert(params).await,
"monitoring.acknowledge-alert" => self.handle_monitoring_acknowledge_alert(params).await,
"monitoring.export" => self.handle_monitoring_export(params).await,
// System updates
"update.check" => self.handle_update_check().await,

View File

@@ -116,6 +116,80 @@ impl RpcHandler {
Ok(serde_json::json!({ "updated": true, "kind": kind_str }))
}
/// monitoring.export — export metrics as CSV or JSON
pub(super) async fn handle_monitoring_export(
&self,
params: Option<serde_json::Value>,
) -> Result<serde_json::Value> {
debug!("Exporting metrics");
let format = params
.as_ref()
.and_then(|p| p.get("format"))
.and_then(|v| v.as_str())
.unwrap_or("csv");
let resolution = params
.as_ref()
.and_then(|p| p.get("resolution"))
.and_then(|v| v.as_str())
.unwrap_or("minute");
let count = params
.as_ref()
.and_then(|p| p.get("count"))
.and_then(|v| v.as_u64())
.unwrap_or(1440) as usize;
let count = count.min(1440);
let data = match resolution {
"quarter_hour" | "15min" => self.metrics_store.history_quarter_hours(count).await,
_ => self.metrics_store.history_minutes(count).await,
};
match format {
"json" => {
Ok(serde_json::json!({
"format": "json",
"resolution": resolution,
"count": data.len(),
"data": data,
}))
}
_ => {
// CSV format
let mut csv = String::from(
"timestamp,cpu_percent,mem_used_bytes,mem_total_bytes,disk_used_bytes,disk_total_bytes,net_rx_bytes,net_tx_bytes,load_avg_1,load_avg_5,load_avg_15,rpc_latency_ms,ws_connections\n"
);
for snapshot in &data {
csv.push_str(&format!(
"{},{:.1},{},{},{},{},{},{},{:.2},{:.2},{:.2},{:.1},{}\n",
snapshot.timestamp,
snapshot.system.cpu_percent,
snapshot.system.mem_used_bytes,
snapshot.system.mem_total_bytes,
snapshot.system.disk_used_bytes,
snapshot.system.disk_total_bytes,
snapshot.system.net_rx_bytes,
snapshot.system.net_tx_bytes,
snapshot.system.load_avg_1,
snapshot.system.load_avg_5,
snapshot.system.load_avg_15,
snapshot.rpc_latency_ms,
snapshot.ws_connections,
));
}
Ok(serde_json::json!({
"format": "csv",
"resolution": resolution,
"count": data.len(),
"csv": csv,
}))
}
}
}
/// monitoring.acknowledge-alert — acknowledge a fired alert
pub(super) async fn handle_monitoring_acknowledge_alert(
&self,