Files
nerd-monitor/cmd/server/main.go
Ducky SSH User 8cb33dbc90 feat: implement real-time updates and enhance monitoring system
- Add structured logging with slog throughout application
- Implement real-time updates using Server-Sent Events and HTMX
- Add broadcaster system for instant UI updates when agents report stats
- Replace meta refresh with HTMX-powered seamless updates
- Add new API endpoints for HTMX fragments and SSE events
- Update templates to use HTMX for instant data refresh
- Enhance README with real-time features and updated documentation
- Remove obsolete template generation file
2025-12-20 08:09:02 +00:00

89 lines
2.5 KiB
Go

package main
import (
"flag"
"log/slog"
"net/http"
"os"
"os/signal"
"syscall"
"github.com/go-chi/chi/v5"
"nerd-monitor/internal/api"
"nerd-monitor/internal/auth"
"nerd-monitor/internal/store"
"nerd-monitor/internal/ui"
)
func main() {
var (
addr = flag.String("addr", "0.0.0.0", "server address")
port = flag.String("port", "8080", "server port")
username = flag.String("username", "admin", "admin username")
password = flag.String("password", "admin", "admin password")
)
flag.Parse()
// Set up verbose logging
slog.SetLogLoggerLevel(slog.LevelDebug)
// Initialize dependencies
s := store.New()
authMgr := auth.New(*username, *password)
apiHandler := api.New(s)
uiHandler := ui.New(s, authMgr)
// Setup router
r := chi.NewRouter()
// Public routes (no auth required)
r.Post("/api/report", apiHandler.ReportStats)
r.Get("/api/agents", apiHandler.ListAgents)
r.Get("/api/agents/{id}", apiHandler.GetAgent)
r.Get("/login", uiHandler.Login)
r.Post("/login", uiHandler.Login)
// Public routes (no auth required)
r.Post("/api/report", apiHandler.ReportStats)
r.Get("/api/agents", apiHandler.ListAgents)
r.Get("/api/agents/{id}", apiHandler.GetAgent)
// Protected routes (auth required)
r.Group(func(protectedRoutes chi.Router) {
protectedRoutes.Use(authMgr.Middleware)
protectedRoutes.Get("/", uiHandler.Dashboard)
protectedRoutes.Get("/agents/{id}", uiHandler.AgentDetail)
protectedRoutes.Get("/api/dashboard/table", uiHandler.GetDashboardTable)
protectedRoutes.Get("/api/agents/{id}/stats", uiHandler.GetAgentStats)
protectedRoutes.Get("/api/events", uiHandler.Events)
protectedRoutes.Post("/agents/{id}/hostname", uiHandler.UpdateAgentHostname)
protectedRoutes.Post("/logout", uiHandler.Logout)
protectedRoutes.Post("/api/agents/remove-stale", uiHandler.RemoveStaleAgents)
protectedRoutes.Post("/api/agents/{id}/delete", uiHandler.DeleteAgent)
})
// Setup server
server := &http.Server{
Addr: *addr + ":" + *port,
Handler: r,
}
// Graceful shutdown
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
go func() {
<-sigChan
slog.Info("Shutting down server...")
server.Close()
os.Exit(0)
}()
slog.Info("Starting server", "addr", *addr+":"+*port, "url", "http://"+*addr+":"+*port)
slog.Info("Login credentials", "username", *username, "password", *password)
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
slog.Error("Server error", "error", err)
os.Exit(1)
}
}