fix: Leer apps desde monitored_apps.json en lugar de AppManager en memoria

Problema:
- El panel web y logs.html no mostraban las apps descubiertas
- /api/apps solo listaba apps registradas vía API (AppManager en memoria)
- Las apps descubiertas por discovery solo estaban en monitored_apps.json
- El AppManager no conocía las apps existentes en systemd

Solución:
- Modificar /api/apps para leer directamente desde monitored_apps.json
- Consultar estado de systemd en tiempo real para cada app
- Modificar get_app_status para leer desde JSON y consultar métricas
- Buscar procesos por nombre de app o entry_point

Cambios:
- list_apps_handler: Lee desde ConfigManager, consulta systemd
- get_app_status_handler: Lee desde JSON, obtiene PID/CPU/RAM de sysinfo
- Retorna status correcto: Running, Stopped, Failed, Starting, Stopping
- Incluye puerto y service_name en respuesta de /api/apps

Ahora el panel web mostrará todas las apps (descubiertas + registradas)
This commit is contained in:
2026-01-18 03:43:53 -05:00
parent 246b5c8342
commit f9e6439b24

View File

@@ -125,21 +125,62 @@ pub async fn restart_app_handler(
} }
pub async fn get_app_status_handler( pub async fn get_app_status_handler(
State(state): State<Arc<ApiState>>, State(_state): State<Arc<ApiState>>,
Path(app_name): Path<String>, Path(app_name): Path<String>,
) -> Result<Json<ApiResponse<AppStatusResponse>>, StatusCode> { ) -> Result<Json<ApiResponse<AppStatusResponse>>, StatusCode> {
use crate::config::get_config_manager;
use crate::systemd::SystemCtl;
use crate::models::{AppStatus, ServiceStatus};
match state.app_manager.get_app_status(&app_name) { let config_manager = get_config_manager();
Some(managed_app) => { let apps = config_manager.get_apps();
let response = AppStatusResponse {
name: managed_app.name, // Buscar la app en monitored_apps.json
status: managed_app.status.as_str().to_string(), let app = apps.iter().find(|a| a.name == app_name);
pid: managed_app.pid,
cpu_usage: managed_app.cpu_usage, match app {
memory_usage: format!("{:.2} MB", managed_app.memory_usage as f64 / 1024.0 / 1024.0), Some(app) => {
systemd_status: managed_app.systemd_status.as_str().to_string(), let service_name = format!("siax-app-{}.service", app.name);
last_updated: managed_app.last_updated, let systemd_status = SystemCtl::status(&service_name);
// Obtener métricas del proceso
let mut sys = System::new_all();
sys.refresh_all();
let mut pid = None;
let mut cpu_usage = 0.0;
let mut memory_mb = 0.0;
// Buscar proceso por nombre de app
for (process_pid, process) in sys.processes() {
let cmd = process.cmd().join(" ");
if cmd.contains(&app.name) || cmd.contains(&app.entry_point) {
pid = Some(process_pid.as_u32() as i32);
cpu_usage = process.cpu_usage();
memory_mb = process.memory() as f64 / 1024.0 / 1024.0;
break;
}
}
let status = match systemd_status {
ServiceStatus::Active => "Running",
ServiceStatus::Inactive => "Stopped",
ServiceStatus::Failed => "Failed",
ServiceStatus::Activating => "Starting",
ServiceStatus::Deactivating => "Stopping",
ServiceStatus::Unknown => "Unknown",
}; };
let response = AppStatusResponse {
name: app.name.clone(),
status: status.to_string(),
pid,
cpu_usage,
memory_usage: format!("{:.2} MB", memory_mb),
systemd_status: systemd_status.as_str().to_string(),
last_updated: chrono::Local::now().format("%Y-%m-%d %H:%M:%S").to_string(),
};
Ok(Json(ApiResponse::success(response))) Ok(Json(ApiResponse::success(response)))
} }
None => Ok(Json(ApiResponse::error( None => Ok(Json(ApiResponse::error(
@@ -149,13 +190,49 @@ pub async fn get_app_status_handler(
} }
pub async fn list_apps_handler( pub async fn list_apps_handler(
State(state): State<Arc<ApiState>>, State(_state): State<Arc<ApiState>>,
) -> Result<Json<ApiResponse<AppListResponse>>, StatusCode> { ) -> Result<Json<serde_json::Value>, StatusCode> {
use crate::config::get_config_manager;
use crate::systemd::SystemCtl;
let apps = state.app_manager.list_apps(); // Leer apps desde monitored_apps.json (apps descubiertas + registradas)
let total = apps.len(); let config_manager = get_config_manager();
let monitored_apps = config_manager.get_apps();
Ok(Json(ApiResponse::success(AppListResponse { apps, total }))) // Crear respuesta con información de cada app
let mut apps_with_status = Vec::new();
for app in monitored_apps {
// Verificar estado en systemd
let service_name = format!("siax-app-{}.service", app.name);
let systemd_status = SystemCtl::status(&service_name);
let status = match systemd_status {
crate::models::ServiceStatus::Active => "Running",
crate::models::ServiceStatus::Inactive => "Stopped",
crate::models::ServiceStatus::Failed => "Failed",
crate::models::ServiceStatus::Activating => "Starting",
crate::models::ServiceStatus::Deactivating => "Stopping",
crate::models::ServiceStatus::Unknown => "Unknown",
};
apps_with_status.push(serde_json::json!({
"name": app.name,
"status": status,
"port": app.port,
"service_name": app.service_name,
}));
}
let total = apps_with_status.len();
Ok(Json(serde_json::json!({
"success": true,
"data": {
"apps": apps_with_status,
"total": total
}
})))
} }
pub async fn scan_processes_handler() -> Result<Json<ApiResponse<ProcessScanResponse>>, StatusCode> { pub async fn scan_processes_handler() -> Result<Json<ApiResponse<ProcessScanResponse>>, StatusCode> {