feat: M14 — Observability (dashboard charts, agent fleet, stats API, metrics, structured logging, rollback)

Backend: StatsService with 5 aggregation methods, JSON metrics endpoint, slog-based
structured logging middleware. Stats API: dashboard summary, certificates-by-status,
expiration timeline, job trends, issuance rate. 23 new backend tests.

Frontend: Recharts-powered dashboard with 4 charts (status pie, expiration heatmap,
job trends line, issuance bar), agent fleet overview page with OS/arch grouping and
version breakdown, deployment rollback buttons on version history. 7 new frontend tests.

78 API endpoints, 744+ total tests (658 Go + 86 Vitest).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
shankar0123
2026-03-22 19:46:13 -04:00
parent 2f65dd1a61
commit ee75f149ae
21 changed files with 2125 additions and 28 deletions
+12 -2
View File
@@ -152,6 +152,10 @@ func main() {
agentGroupService := service.NewAgentGroupService(agentGroupRepo, auditService)
logger.Info("initialized all services")
// Initialize stats and metrics services
statsService := service.NewStatsService(certificateRepo, jobRepo, agentRepo)
logger.Info("initialized stats service")
// Initialize API handlers
certificateHandler := handler.NewCertificateHandler(certificateService)
issuerHandler := handler.NewIssuerHandler(issuerService)
@@ -165,6 +169,8 @@ func main() {
agentGroupHandler := handler.NewAgentGroupHandler(agentGroupService)
auditHandler := handler.NewAuditHandler(auditService)
notificationHandler := handler.NewNotificationHandler(notificationService)
statsHandler := handler.NewStatsHandler(statsService)
metricsHandler := handler.NewMetricsHandler(statsService, time.Now())
healthHandler := handler.NewHealthHandler(cfg.Auth.Type)
logger.Info("initialized all handlers")
@@ -208,6 +214,8 @@ func main() {
agentGroupHandler,
auditHandler,
notificationHandler,
statsHandler,
metricsHandler,
healthHandler,
)
logger.Info("registered all API handlers")
@@ -221,9 +229,11 @@ func main() {
AllowedOrigins: cfg.CORS.AllowedOrigins,
})
structuredLogger := middleware.NewLogging(logger)
middlewareStack := []func(http.Handler) http.Handler{
middleware.RequestID,
middleware.Logging,
structuredLogger,
middleware.Recovery,
corsMiddleware,
authMiddleware,
@@ -237,7 +247,7 @@ func main() {
})
middlewareStack = []func(http.Handler) http.Handler{
middleware.RequestID,
middleware.Logging,
structuredLogger,
middleware.Recovery,
rateLimiter,
corsMiddleware,