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
This commit is contained in:
parent
edf7ef97f0
commit
402cbe1890
@ -27,6 +27,7 @@ interface ServicesStatusResponse {
|
|||||||
mlBackend: ServiceStatus;
|
mlBackend: ServiceStatus;
|
||||||
database: ServiceStatus;
|
database: ServiceStatus;
|
||||||
syslogParser: ServiceStatus;
|
syslogParser: ServiceStatus;
|
||||||
|
analyticsAggregator: ServiceStatus;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,7 @@ interface ServicesStatusResponse {
|
|||||||
mlBackend: ServiceStatus;
|
mlBackend: ServiceStatus;
|
||||||
database: ServiceStatus;
|
database: ServiceStatus;
|
||||||
syslogParser: ServiceStatus;
|
syslogParser: ServiceStatus;
|
||||||
|
analyticsAggregator: ServiceStatus;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,6 +322,62 @@ export default function ServicesPage() {
|
|||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
{/* Analytics Aggregator Service */}
|
||||||
|
<Card data-testid="card-analytics-aggregator-service">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="flex items-center gap-2 text-lg">
|
||||||
|
<Activity className="h-5 w-5" />
|
||||||
|
Analytics Aggregator
|
||||||
|
{servicesStatus && getStatusIndicator(servicesStatus.services.analyticsAggregator)}
|
||||||
|
</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-4">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<span className="text-sm text-muted-foreground">Stato:</span>
|
||||||
|
{servicesStatus && getStatusBadge(servicesStatus.services.analyticsAggregator)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{servicesStatus?.services.analyticsAggregator.details?.lastRun && (
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<span className="text-sm text-muted-foreground">Ultima Aggregazione:</span>
|
||||||
|
<Badge variant="outline" className="text-xs">
|
||||||
|
{new Date(servicesStatus.services.analyticsAggregator.details.lastRun).toLocaleString('it-IT')}
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{servicesStatus?.services.analyticsAggregator.details?.hoursSinceLastRun && (
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<span className="text-sm text-muted-foreground">Ore dall'ultimo run:</span>
|
||||||
|
<Badge variant={parseFloat(servicesStatus.services.analyticsAggregator.details.hoursSinceLastRun) < 2 ? "default" : "secondary"}>
|
||||||
|
{servicesStatus.services.analyticsAggregator.details.hoursSinceLastRun}h
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="mt-4 p-3 bg-muted rounded-lg">
|
||||||
|
<p className="text-xs font-medium mb-2">Verifica timer:</p>
|
||||||
|
<code className="text-xs bg-background p-2 rounded block font-mono" data-testid="code-status-aggregator">
|
||||||
|
systemctl status ids-analytics-aggregator.timer
|
||||||
|
</code>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-4 p-3 bg-muted rounded-lg">
|
||||||
|
<p className="text-xs font-medium mb-2">Avvia aggregazione manualmente:</p>
|
||||||
|
<code className="text-xs bg-background p-2 rounded block font-mono" data-testid="code-run-aggregator">
|
||||||
|
cd /opt/ids && ./deployment/run_analytics.sh
|
||||||
|
</code>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-4 p-3 bg-muted rounded-lg">
|
||||||
|
<p className="text-xs font-medium mb-2">Log:</p>
|
||||||
|
<code className="text-xs bg-background p-2 rounded block font-mono" data-testid="code-log-aggregator">
|
||||||
|
journalctl -u ids-analytics-aggregator.timer -f
|
||||||
|
</code>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Additional Commands */}
|
{/* Additional Commands */}
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
import type { Express } from "express";
|
import type { Express } from "express";
|
||||||
import { createServer, type Server } from "http";
|
import { createServer, type Server } from "http";
|
||||||
import { storage } from "./storage";
|
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<Server> {
|
export async function registerRoutes(app: Express): Promise<Server> {
|
||||||
// Routers
|
// Routers
|
||||||
@ -362,6 +364,7 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
mlBackend: { name: "ML Backend Python", status: "unknown", healthy: false, details: null as any },
|
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 },
|
database: { name: "PostgreSQL Database", status: "unknown", healthy: false, details: null as any },
|
||||||
syslogParser: { name: "Syslog Parser", 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
|
// Check ML Backend Python
|
||||||
@ -446,6 +449,45 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 });
|
res.json({ services });
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
res.status(500).json({ error: "Failed to check services status" });
|
res.status(500).json({ error: "Failed to check services status" });
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user