Files
foxhunt/crates/ml-observability/src/dashboards.rs
jgrusewski 7ef92983f9 fix(clippy): apply cargo clippy --fix across workspace
Mechanical auto-fixes: redundant borrows, clone on Copy, or_insert_with,
single-char push_str, get(0) → first(), needless borrow, let_and_return.
150 files, no behavior changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:17:51 +01:00

139 lines
4.3 KiB
Rust

//! Dashboard system for ML metrics visualization
use anyhow::Result;
use serde::{Deserialize, Serialize};
/// Dashboard configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DashboardConfig {
pub name: String,
pub description: String,
pub refresh_interval_seconds: u64,
pub widgets: Vec<DashboardWidget>,
}
/// Dashboard widget configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DashboardWidget {
pub id: String,
pub title: String,
pub widget_type: WidgetType,
pub metrics: Vec<String>,
pub time_range_minutes: u64,
pub position: WidgetPosition,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WidgetPosition {
pub row: u32,
pub column: u32,
pub width: u32,
pub height: u32,
}
/// Widget types for different visualizations
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum WidgetType {
LineChart,
Histogram,
Gauge,
Counter,
Table,
Heatmap,
}
/// Metrics dashboard
#[derive(Debug)]
pub struct MetricsDashboard {
config: DashboardConfig,
}
impl MetricsDashboard {
pub const fn new(config: DashboardConfig) -> Self {
Self { config }
}
/// Generate dashboard JSON for Grafana/similar tools
pub fn generate_grafana_json(&self) -> Result<String> {
let dashboard = serde_json::json!({
"dashboard": {
"title": self.config.name,
"description": self.config.description,
"refresh": format!("{}s", self.config.refresh_interval_seconds),
"panels": self.config.widgets.iter().map(|w| {
serde_json::json!({
"id": w.id,
"title": w.title,
"type": match w.widget_type {
WidgetType::LineChart => "graph",
WidgetType::Histogram => "histogram",
WidgetType::Gauge => "gauge",
WidgetType::Counter => "stat",
WidgetType::Table => "table",
WidgetType::Heatmap => "heatmap",
},
"gridPos": {
"h": w.position.height,
"w": w.position.width,
"x": w.position.column,
"y": w.position.row
}
})
}).collect::<Vec<_>>()
}
});
Ok(serde_json::to_string_pretty(&dashboard)?)
}
}
/// Create default HFT ML dashboard
pub fn create_hft_ml_dashboard() -> DashboardConfig {
DashboardConfig {
name: "HFT ML Performance".to_owned(),
description: "Real-time monitoring of ML models in HFT trading environment".to_owned(),
refresh_interval_seconds: 5,
widgets: vec![
DashboardWidget {
id: "inference_latency".to_owned(),
title: "Inference Latency (us)".to_owned(),
widget_type: WidgetType::LineChart,
metrics: vec!["ml_inference_latency_microseconds".to_owned()],
time_range_minutes: 15,
position: WidgetPosition {
row: 0,
column: 0,
width: 12,
height: 6,
},
},
DashboardWidget {
id: "prediction_rate".to_owned(),
title: "Predictions per Second".to_owned(),
widget_type: WidgetType::LineChart,
metrics: vec!["ml_predictions_total".to_owned()],
time_range_minutes: 15,
position: WidgetPosition {
row: 6,
column: 0,
width: 6,
height: 6,
},
},
DashboardWidget {
id: "error_rate".to_owned(),
title: "Error Rate".to_owned(),
widget_type: WidgetType::Gauge,
metrics: vec!["ml_error_rate".to_owned()],
time_range_minutes: 15,
position: WidgetPosition {
row: 6,
column: 6,
width: 6,
height: 6,
},
},
],
}
}