diff --git a/src/api/handlers.rs b/src/api/handlers.rs index abfa36a..39d97fb 100644 --- a/src/api/handlers.rs +++ b/src/api/handlers.rs @@ -315,3 +315,46 @@ pub async fn get_monitored_apps_handler() -> Result, Sta Ok(Json(response)) } + +/// Endpoint para obtener los logs de errores del sistema +pub async fn get_system_error_logs() -> Result, 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) + }))) + } + } +} diff --git a/src/main.rs b/src/main.rs index c4554a9..68882f2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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)) diff --git a/web/logs.html b/web/logs.html index 9def69b..8ab88bb 100644 --- a/web/logs.html +++ b/web/logs.html @@ -207,10 +207,38 @@ - + +
+
+ + +
+
+ +
@@ -224,6 +252,19 @@
+ + + @@ -402,8 +443,9 @@ logContainer.appendChild(logEntry); // Auto-scroll - if (autoScroll) { - const terminal = document.getElementById("log-terminal"); + if (autoScroll && currentTab === "app-logs") { + const terminal = + document.getElementById("content-app-logs"); terminal.scrollTop = terminal.scrollHeight; } @@ -460,6 +502,100 @@ `; } + // Tab switching + let currentTab = "app-logs"; + + function switchTab(tabName) { + currentTab = tabName; + + // Update tab buttons + document.querySelectorAll(".tab-button").forEach((btn) => { + btn.classList.remove("border-primary", "text-primary"); + btn.classList.add("border-transparent", "text-[#9dabb9]"); + }); + + const activeTab = document.getElementById(`tab-${tabName}`); + activeTab.classList.remove( + "border-transparent", + "text-[#9dabb9]", + ); + activeTab.classList.add("border-primary", "text-primary"); + + // Update tab content + document.querySelectorAll(".tab-content").forEach((content) => { + content.classList.add("hidden"); + }); + + document + .getElementById(`content-${tabName}`) + .classList.remove("hidden"); + + // Load system errors if switching to that tab + if (tabName === "system-errors") { + loadSystemErrors(); + } + } + + async function loadSystemErrors() { + const container = document.getElementById( + "system-errors-container", + ); + + try { + const response = await fetch("/api/logs/errors"); + const result = await response.json(); + + if ( + result.success && + result.logs && + result.logs.length > 0 + ) { + container.innerHTML = result.logs + .map((line) => { + // Parse log line + let icon = "●"; + let color = "text-white"; + + if (line.includes("[ERROR]")) { + icon = "✖"; + color = "text-red-400"; + } else if (line.includes("[WARN]")) { + icon = "⚠"; + color = "text-yellow-400"; + } else if (line.includes("[INFO]")) { + icon = "ℹ"; + color = "text-blue-400"; + } + + return `
${icon} ${escapeHtml(line)}
`; + }) + .join(""); + + // Auto scroll to bottom + container.scrollTop = container.scrollHeight; + } else if (result.message) { + container.innerHTML = ` +
+ ${result.message} +
+ `; + } else { + container.innerHTML = ` +
+ No hay logs de errores disponibles +
+ `; + } + } catch (error) { + console.error("Error loading system errors:", error); + container.innerHTML = ` +
+ Error cargando logs del sistema +
+ `; + } + } + // Load apps on page load document.addEventListener("DOMContentLoaded", loadApps);