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>
81 lines
2.0 KiB
Go
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)
|
|
}
|
|
}
|