Skip to main content

trustformers_debug/utilities/
health.rs

1//! Health checking and diagnostics utilities
2
3use crate::{DebugConfig, DebugSession, QuickDebugLevel, SimplifiedDebugResult};
4use anyhow::Result;
5use serde::{Deserialize, Serialize};
6
7/// Health check result structure
8#[derive(Debug, Serialize, Deserialize)]
9pub struct HealthCheckResult {
10    pub overall_score: f64,
11    pub status: String,
12    pub issues: Vec<String>,
13    pub critical_issues: bool,
14    pub timestamp: chrono::DateTime<chrono::Utc>,
15}
16
17/// Debug summary structure
18#[derive(Debug, Serialize, Deserialize)]
19pub struct DebugSummary {
20    pub config_hash: String,
21    pub total_debug_runs: usize,
22    pub total_issues: usize,
23    pub critical_issues: usize,
24    pub recommendations: Vec<String>,
25    pub timestamp: chrono::DateTime<chrono::Utc>,
26}
27
28/// Export format options
29#[derive(Debug, Clone)]
30pub enum ExportFormat {
31    Json,
32    Csv,
33    Html,
34}
35
36/// Debug template types
37#[derive(Debug, Clone)]
38pub enum DebugTemplate {
39    Development,
40    Production,
41    Training,
42    Research,
43}
44
45/// Health checking utilities
46pub struct HealthChecker;
47
48impl HealthChecker {
49    /// Quick model health check with automatic issue detection
50    pub async fn quick_health_check<T>(model: &T) -> Result<HealthCheckResult> {
51        let result = crate::quick_debug(model, QuickDebugLevel::Light).await?;
52
53        let health_score = match &result {
54            SimplifiedDebugResult::Light(health) => health.score,
55            SimplifiedDebugResult::Standard { health, .. } => health.score,
56            SimplifiedDebugResult::Deep(report) => {
57                let summary = report.summary();
58                100.0 - (summary.critical_issues as f64 * 20.0 + summary.total_issues as f64 * 5.0)
59            },
60            SimplifiedDebugResult::Production(anomaly) => {
61                100.0 - (anomaly.anomaly_count as f64 * 10.0)
62            },
63        };
64
65        Ok(HealthCheckResult {
66            overall_score: health_score,
67            status: Self::score_to_status(health_score),
68            issues: result.recommendations(),
69            critical_issues: result.has_critical_issues(),
70            timestamp: chrono::Utc::now(),
71        })
72    }
73
74    /// Convert health score to status string
75    pub fn score_to_status(score: f64) -> String {
76        match score {
77            s if s >= 90.0 => "Excellent".to_string(),
78            s if s >= 75.0 => "Good".to_string(),
79            s if s >= 50.0 => "Fair".to_string(),
80            s if s >= 25.0 => "Poor".to_string(),
81            _ => "Critical".to_string(),
82        }
83    }
84
85    /// Generate debug report summary
86    pub fn generate_debug_summary(
87        config: &DebugConfig,
88        results: &[SimplifiedDebugResult],
89    ) -> DebugSummary {
90        let mut total_issues = 0;
91        let mut critical_issues = 0;
92        let mut all_recommendations = Vec::new();
93
94        for result in results {
95            match result {
96                SimplifiedDebugResult::Light(health) => {
97                    if health.score < 50.0 {
98                        critical_issues += 1;
99                    }
100                    total_issues += 1;
101                },
102                SimplifiedDebugResult::Standard { health, .. } => {
103                    if health.score < 50.0 {
104                        critical_issues += 1;
105                    }
106                    total_issues += 1;
107                },
108                SimplifiedDebugResult::Deep(report) => {
109                    let summary = report.summary();
110                    total_issues += summary.total_issues;
111                    critical_issues += summary.critical_issues;
112                },
113                SimplifiedDebugResult::Production(anomaly) => {
114                    total_issues += anomaly.anomaly_count;
115                    if anomaly.severity_level.to_lowercase().contains("critical")
116                        || anomaly.severity_level.to_lowercase().contains("high")
117                    {
118                        critical_issues += 1;
119                    }
120                },
121            }
122
123            all_recommendations.extend(result.recommendations());
124        }
125
126        all_recommendations.dedup();
127
128        DebugSummary {
129            config_hash: Self::hash_config(config),
130            total_debug_runs: results.len(),
131            total_issues,
132            critical_issues,
133            recommendations: all_recommendations,
134            timestamp: chrono::Utc::now(),
135        }
136    }
137
138    /// Export debug data in various formats
139    pub async fn export_debug_data(
140        session: &DebugSession,
141        format: ExportFormat,
142        output_path: &str,
143    ) -> Result<String> {
144        let report = session.generate_snapshot().await?;
145
146        match format {
147            ExportFormat::Json => {
148                let json_data = serde_json::to_string_pretty(&report)?;
149                tokio::fs::write(output_path, json_data).await?;
150            },
151            ExportFormat::Csv => {
152                let csv_data = Self::report_to_csv(&report)?;
153                tokio::fs::write(output_path, csv_data).await?;
154            },
155            ExportFormat::Html => {
156                let html_data = Self::report_to_html(&report)?;
157                tokio::fs::write(output_path, html_data).await?;
158            },
159        }
160
161        Ok(format!("Debug data exported to {}", output_path))
162    }
163
164    /// Create a debug session template for common use cases
165    pub fn create_debug_template(template_type: DebugTemplate) -> DebugConfig {
166        match template_type {
167            DebugTemplate::Development => DebugConfig {
168                enable_tensor_inspection: true,
169                enable_gradient_debugging: true,
170                enable_model_diagnostics: true,
171                enable_visualization: true,
172                enable_memory_profiling: true,
173                enable_computation_graph_analysis: true,
174                max_tracked_tensors: 1000,
175                max_gradient_history: 100,
176                sampling_rate: 1.0,
177                ..Default::default()
178            },
179            DebugTemplate::Production => DebugConfig {
180                enable_tensor_inspection: false,
181                enable_gradient_debugging: false,
182                enable_model_diagnostics: false,
183                enable_visualization: false,
184                enable_memory_profiling: true,
185                enable_computation_graph_analysis: false,
186                max_tracked_tensors: 10,
187                max_gradient_history: 10,
188                sampling_rate: 0.1,
189                ..Default::default()
190            },
191            DebugTemplate::Training => DebugConfig {
192                enable_tensor_inspection: true,
193                enable_gradient_debugging: true,
194                enable_model_diagnostics: true,
195                enable_visualization: false,
196                enable_memory_profiling: true,
197                enable_computation_graph_analysis: true,
198                max_tracked_tensors: 500,
199                max_gradient_history: 50,
200                sampling_rate: 0.5,
201                ..Default::default()
202            },
203            DebugTemplate::Research => DebugConfig {
204                enable_tensor_inspection: true,
205                enable_gradient_debugging: true,
206                enable_model_diagnostics: true,
207                enable_visualization: true,
208                enable_memory_profiling: true,
209                enable_computation_graph_analysis: true,
210                max_tracked_tensors: 2000,
211                max_gradient_history: 200,
212                sampling_rate: 1.0,
213                ..Default::default()
214            },
215        }
216    }
217
218    /// Hash configuration for tracking
219    fn hash_config(config: &DebugConfig) -> String {
220        use std::collections::hash_map::DefaultHasher;
221        use std::hash::{Hash, Hasher};
222
223        let mut hasher = DefaultHasher::new();
224        format!("{:?}", config).hash(&mut hasher);
225        format!("{:x}", hasher.finish())
226    }
227
228    /// Convert report to CSV format
229    fn report_to_csv(_report: &crate::DebugReport) -> Result<String> {
230        // Simple CSV conversion - in a real implementation this would be more sophisticated
231        Ok(format!(
232            "timestamp,score,issues\n{},{},{}",
233            chrono::Utc::now().to_rfc3339(),
234            0, // Placeholder - would extract from report.summary()
235            0  // Placeholder - would extract from report.summary()
236        ))
237    }
238
239    /// Convert report to HTML format
240    fn report_to_html(report: &crate::DebugReport) -> Result<String> {
241        // Simple HTML conversion - in a real implementation this would be more sophisticated
242        Ok(format!(
243            r#"
244<!DOCTYPE html>
245<html>
246<head>
247    <title>Debug Report</title>
248    <style>
249        body {{ font-family: Arial, sans-serif; margin: 40px; }}
250        .report {{ background: #f5f5f5; padding: 20px; border-radius: 5px; }}
251    </style>
252</head>
253<body>
254    <h1>TrustformeRS Debug Report</h1>
255    <div class="report">
256        <pre>{}</pre>
257    </div>
258</body>
259</html>
260        "#,
261            serde_json::to_string_pretty(report)?
262        ))
263    }
264}