Files
nvllama-watchdog/exporters/prometheus.go
2026-10-11 12:24:01 +02:00

76 lines
1.6 KiB
Go

// exporters/prometheus.go
package exporters
import (
"context"
"fmt"
"net/http"
"sort"
"strings"
"sync"
"git.govekar.net/LovroG05/nvllama-watchdog/core"
)
type PrometheusExporter struct {
mu sync.RWMutex
metrics []core.Metric
addr string
}
func NewPrometheusExporter(addr string) *PrometheusExporter {
return &PrometheusExporter{addr: addr}
}
func (e *PrometheusExporter) Name() string { return "prometheus" }
func (e *PrometheusExporter) Write(_ context.Context, ms []core.Metric) error {
e.mu.Lock()
e.metrics = ms
e.mu.Unlock()
return nil
}
// Handler serves the /metrics HTTP endpoint.
func (e *PrometheusExporter) Handler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
e.mu.RLock()
defer e.mu.RUnlock()
w.Header().Set("Content-Type", "text/plain; version=0.0.4")
// group by name for HELP/TYPE (simplified)
sort.Slice(e.metrics, func(i, j int) bool {
return e.metrics[i].Name < e.metrics[j].Name
})
var b strings.Builder
for _, m := range e.metrics {
b.WriteString(fmt.Sprintf("%s%s %g\n", m.Name, formatLabels(m.Labels), m.Value))
}
fmt.Fprint(w, b.String())
})
}
func formatLabels(l map[string]string) string {
if len(l) == 0 {
return " "
}
keys := make([]string, 0, len(l))
for k := range l {
keys = append(keys, k)
}
sort.Strings(keys)
parts := make([]string, len(keys))
for i, k := range keys {
parts[i] = fmt.Sprintf(`%s="%s"`, k, l[k])
}
return " {" + strings.Join(parts, ",") + "}"
}
func (e *PrometheusExporter) Start() error {
return http.ListenAndServe(e.addr, e.Handler())
}
func (e *PrometheusExporter) Addr() string {
return e.addr
}