Files
unraid-exporter/main.go
2025-11-25 10:52:34 +00:00

130 lines
2.8 KiB
Go

package main
import (
"context"
"flag"
"fmt"
"log"
"net/http"
"os"
"time"
graphql "github.com/hasura/go-graphql-client"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var (
interval int
timeout int
port int
endpoint string
graphqlClient *graphql.Client
)
var statuses = []string{
"NEVER_RUN",
"RUNNING",
"PAUSED",
"COMPLETED",
"CANCELLED",
"FAILED",
}
func init() {
flag.IntVar(&interval, "interval", 30, "Duration, in seconds, between checks")
flag.IntVar(&timeout, "timeout", 5000, "Timeout in ms when connecting to Unraid")
flag.IntVar(&port, "port", 9091, "The port to listen on")
flag.StringVar(&endpoint, "endpoint", "", "The Unraid GraphQL endpoint")
flag.Parse()
envEndpoint := os.Getenv("UNRAID_ENDPOINT")
if envEndpoint != "" {
endpoint = envEndpoint
}
if endpoint == "" {
panic("Endpoint must be provided")
}
token := os.Getenv("UNRAID_TOKEN")
if token == "" {
panic("UNRAID_TOKEN env var must be provided")
}
graphqlClient = graphql.NewClient(
endpoint,
&http.Client{
Timeout: time.Millisecond * time.Duration(timeout),
},
).
WithRequestModifier(func(r *http.Request) {
r.Header.Set("content-type", "application/json")
r.Header.Set("x-api-key", token)
})
}
func main() {
fmt.Println("Unraid-exporter")
collector := newUnraidCollector()
prometheus.MustRegister(collector)
go func() {
if err := fetchUnraidStatus(collector); err != nil {
fmt.Printf("failed to get status from Unraid: %v\n", err)
}
for range time.Tick(time.Second * time.Duration(interval)) {
if err := fetchUnraidStatus(collector); err != nil {
fmt.Printf("failed to get status from Unraid: %v\n", err)
}
}
}()
http.Handle("/metrics", promhttp.Handler())
fmt.Printf("Starting server on %d\n", port)
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), nil))
}
func fetchUnraidStatus(collector *UnraidCollector) error {
var query struct {
Array struct {
ParityCheckStatus struct {
Progress int64
Status string
Date string
Duration int64
Errors int64
Speed string
}
}
}
err := graphqlClient.Query(context.Background(), &query, nil)
if err != nil {
return err
}
collector.metrics = []prometheus.Metric{
prometheus.MustNewConstMetric(
collector.parityProgressMetric, prometheus.CounterValue,
float64(query.Array.ParityCheckStatus.Progress),
),
prometheus.MustNewConstMetric(
collector.parityErrorCountMetric, prometheus.CounterValue,
float64(query.Array.ParityCheckStatus.Errors),
),
}
for _, status := range statuses {
val := 0
if status == query.Array.ParityCheckStatus.Status {
val = 1
}
collector.metrics = append(collector.metrics, prometheus.MustNewConstMetric(
collector.parityStatusMetric, prometheus.CounterValue,
float64(val), status,
))
}
return nil
}