feat: Agregar sistema de tabs en logs.html con visualización de errores del sistema
Backend (handlers.rs + main.rs): - Nuevo endpoint GET /api/logs/errors - Lee logs/errors.log y retorna últimas 500 líneas - Parsea y formatea logs con niveles (INFO, WARN, ERROR) Frontend (logs.html): - Sistema de tabs con 2 pestañas: * Tab 1: "Logs de App" - logs en tiempo real vía WebSocket (journalctl) * Tab 2: "Errores del Sistema" - logs del archivo errors.log - Carga apps desde /api/apps (ya usaba el JSON correctamente) - Colorización por nivel de log: * ERROR = rojo * WARN = amarillo * INFO = azul - Auto-scroll en ambos tabs - Diseño consistente con el resto de la UI Ahora logs.html muestra: ✅ Logs de aplicaciones individuales (systemd/journalctl) ✅ Logs de errores del sistema SIAX Monitor (logs/errors.log) ✅ Navegación por tabs ✅ Lista de apps desde monitored_apps.json
This commit is contained in:
@@ -315,3 +315,46 @@ pub async fn get_monitored_apps_handler() -> Result<Json<serde_json::Value>, Sta
|
||||
|
||||
Ok(Json(response))
|
||||
}
|
||||
|
||||
/// Endpoint para obtener los logs de errores del sistema
|
||||
pub async fn get_system_error_logs() -> Result<Json<serde_json::Value>, StatusCode> {
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
let log_path = "logs/errors.log";
|
||||
|
||||
// Verificar si el archivo existe
|
||||
if !Path::new(log_path).exists() {
|
||||
return Ok(Json(serde_json::json!({
|
||||
"success": true,
|
||||
"logs": [],
|
||||
"message": "Archivo de logs no encontrado"
|
||||
})));
|
||||
}
|
||||
|
||||
// Leer el archivo
|
||||
match fs::read_to_string(log_path) {
|
||||
Ok(content) => {
|
||||
// Dividir en líneas y tomar las últimas 500
|
||||
let lines: Vec<&str> = content.lines().collect();
|
||||
let total = lines.len();
|
||||
let recent_lines: Vec<&str> = if lines.len() > 500 {
|
||||
lines[lines.len() - 500..].to_vec()
|
||||
} else {
|
||||
lines
|
||||
};
|
||||
|
||||
Ok(Json(serde_json::json!({
|
||||
"success": true,
|
||||
"logs": recent_lines,
|
||||
"total_lines": total
|
||||
})))
|
||||
}
|
||||
Err(e) => {
|
||||
Ok(Json(serde_json::json!({
|
||||
"success": false,
|
||||
"error": format!("Error leyendo archivo: {}", e)
|
||||
})))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ async fn main() {
|
||||
let api_router = Router::new()
|
||||
.route("/api/health", get(api::health_handler))
|
||||
.route("/api/monitored", get(api::get_monitored_apps_handler))
|
||||
.route("/api/logs/errors", get(api::get_system_error_logs))
|
||||
.route("/api/apps", get(api::list_apps_handler).post(api::register_app_handler))
|
||||
.route("/api/apps/:name", delete(api::unregister_app_handler))
|
||||
.route("/api/apps/:name/status", get(api::get_app_status_handler))
|
||||
|
||||
Reference in New Issue
Block a user