package main import ( "context" "log/slog" "net/http" "os" "os/signal" "syscall" "time" "github.com/joho/godotenv" httpadapter "gitea.nik4nao.com/nik/home-services/alert-bridge/internal/adapters/primary/http" "gitea.nik4nao.com/nik/home-services/alert-bridge/internal/adapters/secondary/discordwebhook" "gitea.nik4nao.com/nik/home-services/alert-bridge/internal/app" "gitea.nik4nao.com/nik/home-services/alert-bridge/internal/config" "gitea.nik4nao.com/nik/home-services/alert-bridge/internal/logger" "gitea.nik4nao.com/nik/home-services/alert-bridge/internal/telemetry" ) var version = "dev" func main() { _ = godotenv.Load() cfg, err := config.Load() if err != nil { os.Stderr.WriteString("config error: " + err.Error() + "\n") os.Exit(1) } log := logger.New(cfg.LogFormat, cfg.LogLevel) slog.SetDefault(log) log.Info("starting alert-bridge", "version", version, "http_port", cfg.HTTPPort, "log_level", cfg.LogLevel, "log_format", cfg.LogFormat, ) ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() ctx = logger.WithLogger(ctx, log) shutdown, err := telemetry.Setup(ctx, "alert-bridge", version, cfg) if err != nil { log.Error("telemetry setup failed", "err", err) os.Exit(1) } if cfg.OTELEndpoint != "" { log.Info("telemetry enabled", "endpoint", cfg.OTELEndpoint) } else { log.Debug("telemetry disabled") } notifier := discordwebhook.New(cfg.DiscordWebhookURL, cfg.MentionUserID) alertApp := app.NewAlertApp(notifier) alertHandler := httpadapter.NewHandler(alertApp, cfg.APIKey) mux := http.NewServeMux() mux.Handle("POST /alerts", alertHandler) mux.HandleFunc("GET /healthz", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) srv := &http.Server{ Addr: ":" + cfg.HTTPPort, Handler: mux, ReadHeaderTimeout: 5 * time.Second, } go func() { log.Info("alert-bridge listening", "addr", srv.Addr) if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Error("serve failed", "err", err) } }() <-ctx.Done() log.Info("shutdown signal received, draining") shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() if err := srv.Shutdown(shutdownCtx); err != nil { log.Error("http server shutdown failed", "err", err) } log.Info("shutdown complete") if err := shutdown(context.Background()); err != nil { log.Error("telemetry shutdown error", "err", err) } }