Files
nixos-exporter/main.go
Torjus Håkestad 9c29505814 feat: add nixos_flake_info metric with current and remote revisions
Add a new info metric that exposes the current system's flake revision
and the latest remote revision as labels. This makes it easier to see
exactly which revision is deployed vs available.

Also adds version constant to Go code and extracts it in flake.nix,
providing a single source of truth for the version.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-07 00:16:19 +01:00

81 lines
2.0 KiB
Go

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.0"
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(`<html>
<head><title>NixOS Exporter</title></head>
<body>
<h1>NixOS Exporter</h1>
<p><a href="/metrics">Metrics</a></p>
</body>
</html>`))
})
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)
}
}