package main import ( "context" "log" "net/http" "os/signal" "syscall" "time" "gitea.wayfinderak.com/wayfinderak/log-guardian/internal/actions" "gitea.wayfinderak.com/wayfinderak/log-guardian/internal/alerts" "gitea.wayfinderak.com/wayfinderak/log-guardian/internal/analysis" "gitea.wayfinderak.com/wayfinderak/log-guardian/internal/config" "gitea.wayfinderak.com/wayfinderak/log-guardian/internal/loki" "gitea.wayfinderak.com/wayfinderak/log-guardian/internal/rules" "gitea.wayfinderak.com/wayfinderak/log-guardian/internal/server" "gitea.wayfinderak.com/wayfinderak/log-guardian/internal/store" ) func main() { cfg := config.Load() ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() fileStore := store.NewFileStore(cfg.DataPath) lokiClient := loki.New(cfg.LokiURL, cfg.LokiTenantID, cfg.LokiUsername, cfg.LokiPassword) var analyzer analysis.Analyzer = analysis.NoopAnalyzer{} if cfg.AnalysisProvider == "ollama" { analyzer = analysis.NewOllamaAnalyzer(cfg.OllamaURL, cfg.OllamaModel) } actionRunner := actions.NewRunner(cfg.DryRunActions) dispatcher := alerts.NewDispatcher() engine := rules.NewEngine(fileStore, lokiClient, analyzer, actionRunner, dispatcher) go engine.Start(ctx, cfg.PollInterval) httpServer := &http.Server{Addr: cfg.Addr, Handler: server.New(fileStore, engine, lokiClient, dispatcher, cfg.AuthUsername, cfg.AuthPassword).Routes()} go func() { <-ctx.Done() shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() _ = httpServer.Shutdown(shutdownCtx) }() log.Printf("log-guardian listening on %s", cfg.Addr) if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatal(err) } }