76 lines
1.6 KiB
Go
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
|
|
}
|