From 402cbe1890d9a08e8fd7b036462067af4b6bedaf Mon Sep 17 00:00:00 2001 From: marco370 <48531002-marco370@users.noreply.replit.com> Date: Mon, 24 Nov 2025 10:58:41 +0000 Subject: [PATCH] Add Analytics Aggregator monitoring and status display Integrates Analytics Aggregator status checks into the services overview, updating both backend route handling and frontend display components. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528 Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Event-Id: 1211e51b-5231-4d36-9e68-107ca898152b Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/0sf5i4S --- client/src/pages/Dashboard.tsx | 1 + client/src/pages/Services.tsx | 57 ++++++++++++++++++++++++++++++++++ server/routes.ts | 44 +++++++++++++++++++++++++- 3 files changed, 101 insertions(+), 1 deletion(-) diff --git a/client/src/pages/Dashboard.tsx b/client/src/pages/Dashboard.tsx index 899d48b..375b9fd 100644 --- a/client/src/pages/Dashboard.tsx +++ b/client/src/pages/Dashboard.tsx @@ -27,6 +27,7 @@ interface ServicesStatusResponse { mlBackend: ServiceStatus; database: ServiceStatus; syslogParser: ServiceStatus; + analyticsAggregator: ServiceStatus; }; } diff --git a/client/src/pages/Services.tsx b/client/src/pages/Services.tsx index 0ebb77b..6c778be 100644 --- a/client/src/pages/Services.tsx +++ b/client/src/pages/Services.tsx @@ -19,6 +19,7 @@ interface ServicesStatusResponse { mlBackend: ServiceStatus; database: ServiceStatus; syslogParser: ServiceStatus; + analyticsAggregator: ServiceStatus; }; } @@ -321,6 +322,62 @@ export default function ServicesPage() { + + {/* Analytics Aggregator Service */} + + + + + Analytics Aggregator + {servicesStatus && getStatusIndicator(servicesStatus.services.analyticsAggregator)} + + + +
+ Stato: + {servicesStatus && getStatusBadge(servicesStatus.services.analyticsAggregator)} +
+ + {servicesStatus?.services.analyticsAggregator.details?.lastRun && ( +
+ Ultima Aggregazione: + + {new Date(servicesStatus.services.analyticsAggregator.details.lastRun).toLocaleString('it-IT')} + +
+ )} + + {servicesStatus?.services.analyticsAggregator.details?.hoursSinceLastRun && ( +
+ Ore dall'ultimo run: + + {servicesStatus.services.analyticsAggregator.details.hoursSinceLastRun}h + +
+ )} + +
+

Verifica timer:

+ + systemctl status ids-analytics-aggregator.timer + +
+ +
+

Avvia aggregazione manualmente:

+ + cd /opt/ids && ./deployment/run_analytics.sh + +
+ +
+

Log:

+ + journalctl -u ids-analytics-aggregator.timer -f + +
+
+
{/* Additional Commands */} diff --git a/server/routes.ts b/server/routes.ts index 7d7357e..c2e9040 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -1,7 +1,9 @@ import type { Express } from "express"; import { createServer, type Server } from "http"; import { storage } from "./storage"; -import { insertRouterSchema, insertDetectionSchema, insertWhitelistSchema } from "@shared/schema"; +import { insertRouterSchema, insertDetectionSchema, insertWhitelistSchema, networkAnalytics } from "@shared/schema"; +import { db } from "./db"; +import { desc } from "drizzle-orm"; export async function registerRoutes(app: Express): Promise { // Routers @@ -362,6 +364,7 @@ export async function registerRoutes(app: Express): Promise { mlBackend: { name: "ML Backend Python", status: "unknown", healthy: false, details: null as any }, database: { name: "PostgreSQL Database", status: "unknown", healthy: false, details: null as any }, syslogParser: { name: "Syslog Parser", status: "unknown", healthy: false, details: null as any }, + analyticsAggregator: { name: "Analytics Aggregator Timer", status: "unknown", healthy: false, details: null as any }, }; // Check ML Backend Python @@ -446,6 +449,45 @@ export async function registerRoutes(app: Express): Promise { }; } + // Check Analytics Aggregator (via last record timestamp) + try { + const latestAnalytics = await db + .select() + .from(networkAnalytics) + .orderBy(desc(networkAnalytics.date), desc(networkAnalytics.hour)) + .limit(1); + + if (latestAnalytics.length > 0) { + const lastRun = new Date(latestAnalytics[0].date); + const hoursSinceLastRun = (Date.now() - lastRun.getTime()) / (1000 * 60 * 60); + + if (hoursSinceLastRun < 2) { + services.analyticsAggregator.status = "running"; + services.analyticsAggregator.healthy = true; + services.analyticsAggregator.details = { + lastRun: latestAnalytics[0].date, + hoursSinceLastRun: hoursSinceLastRun.toFixed(1), + }; + } else { + services.analyticsAggregator.status = "idle"; + services.analyticsAggregator.healthy = false; + services.analyticsAggregator.details = { + lastRun: latestAnalytics[0].date, + hoursSinceLastRun: hoursSinceLastRun.toFixed(1), + warning: "No aggregation in last 2 hours", + }; + } + } else { + services.analyticsAggregator.status = "idle"; + services.analyticsAggregator.healthy = false; + services.analyticsAggregator.details = { error: "No analytics data found" }; + } + } catch (error: any) { + services.analyticsAggregator.status = "error"; + services.analyticsAggregator.healthy = false; + services.analyticsAggregator.details = { error: error.message }; + } + res.json({ services }); } catch (error: any) { res.status(500).json({ error: "Failed to check services status" });