Add real-time log monitoring and system stats dashboard

Implements a comprehensive monitoring system for the admin interface:

Backend:
- New monitoring package with Redis ring buffer for log storage
- Zerolog MultiWriter to capture logs to Redis
- System stats collection (CPU, memory, disk, goroutines, GC)
- HTTP metrics middleware (request counts, latency, error rates)
- Asynq queue stats for worker process
- WebSocket endpoint for real-time log streaming
- Admin auth middleware now accepts token in query params (for WebSocket)

Frontend:
- New monitoring page with tabs (Overview, Logs, API Stats, Worker Stats)
- Real-time log viewer with level filtering and search
- System stats cards showing CPU, memory, goroutines, uptime
- HTTP endpoint statistics table
- Asynq queue depth visualization
- Enable/disable monitoring toggle in settings

Memory safeguards:
- Max 200 unique endpoints tracked
- Hourly stats reset to prevent unbounded growth
- Max 1000 log entries in ring buffer
- Max 1000 latency samples for P95 calculation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-12-09 10:26:40 -06:00
parent 12eac24632
commit eb127fda20
31 changed files with 2880 additions and 213 deletions

View File

@@ -13,6 +13,7 @@ import (
"github.com/treytartt/casera-api/internal/handlers"
"github.com/treytartt/casera-api/internal/i18n"
"github.com/treytartt/casera-api/internal/middleware"
"github.com/treytartt/casera-api/internal/monitoring"
"github.com/treytartt/casera-api/internal/push"
"github.com/treytartt/casera-api/internal/repositories"
"github.com/treytartt/casera-api/internal/services"
@@ -23,13 +24,14 @@ const Version = "2.0.0"
// Dependencies holds all dependencies needed by the router
type Dependencies struct {
DB *gorm.DB
Cache *services.CacheService
Config *config.Config
EmailService *services.EmailService
PDFService *services.PDFService
PushClient *push.Client // Direct APNs/FCM client
StorageService *services.StorageService
DB *gorm.DB
Cache *services.CacheService
Config *config.Config
EmailService *services.EmailService
PDFService *services.PDFService
PushClient *push.Client // Direct APNs/FCM client
StorageService *services.StorageService
MonitoringService *monitoring.Service
}
// SetupRouter creates and configures the Gin router
@@ -51,6 +53,13 @@ func SetupRouter(deps *Dependencies) *gin.Engine {
r.Use(corsMiddleware(cfg))
r.Use(i18n.Middleware())
// Monitoring metrics middleware (if monitoring is enabled)
if deps.MonitoringService != nil {
if metricsMiddleware := deps.MonitoringService.MetricsMiddleware(); metricsMiddleware != nil {
r.Use(metricsMiddleware.(gin.HandlerFunc))
}
}
// Serve landing page static files (if static directory is configured)
staticDir := cfg.Server.StaticDir
if staticDir != "" {
@@ -137,11 +146,17 @@ func SetupRouter(deps *Dependencies) *gin.Engine {
mediaHandler = handlers.NewMediaHandler(documentRepo, taskRepo, residenceRepo, deps.StorageService)
}
// Set up admin routes (separate auth system)
// Set up admin routes with monitoring handler (if available)
var monitoringHandler *monitoring.Handler
if deps.MonitoringService != nil {
monitoringHandler = deps.MonitoringService.Handler()
}
adminDeps := &admin.Dependencies{
EmailService: deps.EmailService,
PushClient: deps.PushClient,
OnboardingService: onboardingService,
MonitoringHandler: monitoringHandler,
}
admin.SetupRoutes(r, deps.DB, cfg, adminDeps)