package main import ( "context" "log/slog" "net/http" "os" "os/signal" "syscall" "time" "git.t-juice.club/torjus/nixos-exporter/collector" "git.t-juice.club/torjus/nixos-exporter/config" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" ) const version = "0.2.3" func main() { cfg, err := config.Parse() if err != nil { slog.Error("Failed to parse config", "error", err) os.Exit(1) } // Register generation collector genCollector := collector.NewGenerationCollector() prometheus.MustRegister(genCollector) slog.Info("Registered generation collector") // Register flake collector if enabled if cfg.FlakeCollector { flakeCollector := collector.NewFlakeCollector(cfg.FlakeURL, cfg.FlakeCheckInterval) prometheus.MustRegister(flakeCollector) slog.Info("Registered flake collector", "url", cfg.FlakeURL, "check_interval", cfg.FlakeCheckInterval) } mux := http.NewServeMux() mux.Handle("/metrics", promhttp.Handler()) mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { _, _ = w.Write([]byte(` NixOS Exporter

NixOS Exporter

Metrics

`)) }) server := &http.Server{ Addr: cfg.ListenAddr, Handler: mux, ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, IdleTimeout: 60 * time.Second, } // Handle shutdown gracefully ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() go func() { slog.Info("Starting server", "version", version, "addr", cfg.ListenAddr) if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { slog.Error("Server error", "error", err) os.Exit(1) } }() <-ctx.Done() slog.Info("Shutting down server") shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := server.Shutdown(shutdownCtx); err != nil { slog.Error("Failed to shutdown server", "error", err) } }