Files
io-exporter/cmd/metrics.go
T.v.Dein 99222b1cae Refactor exporter (#3)
* refactor exporter code for better readability and structure
* modified startup log output a little
2025-10-23 12:14:33 +02:00

126 lines
2.7 KiB
Go

package cmd
import (
"fmt"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/collectors"
)
// custom labels
type Label struct {
Name, Value string
}
// simple prometheus wrapper
type Metrics struct {
run *prometheus.GaugeVec
latency_r *prometheus.GaugeVec
latency_w *prometheus.GaugeVec
registry *prometheus.Registry
values []string
mode int
}
func NewMetrics(conf *Config) *Metrics {
labels := []string{"file", "maxwait", "exectime"}
LabelLen := 3
for _, label := range conf.Labels {
labels = append(labels, label.Name)
}
metrics := &Metrics{
run: prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "io_exporter_io_operation",
Help: "whether io is working on the pvc, 1=ok, 0=fail",
},
labels,
),
latency_r: prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "io_exporter_io_read_latency",
Help: "how long does the read operation take in seconds",
},
labels,
),
latency_w: prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "io_exporter_io_write_latency",
Help: "how long does the write operation take in seconds",
},
labels,
),
// use fixed size slice to avoid repeated allocs
values: make([]string, LabelLen+len(conf.Labels)),
registry: prometheus.NewRegistry(),
}
if conf.Internals {
metrics.registry.MustRegister(
metrics.run,
metrics.latency_r,
metrics.latency_w,
// we might need to take care of the exporter in terms of
// resources, so also report those internals
collectors.NewGoCollector(
collectors.WithGoCollectorMemStatsMetricsDisabled(),
),
collectors.NewProcessCollector(
collectors.ProcessCollectorOpts{},
),
)
} else {
metrics.registry.MustRegister(metrics.run, metrics.latency_r, metrics.latency_w)
}
// static labels
metrics.values[0] = conf.File
metrics.values[1] = fmt.Sprintf("%d", conf.Timeout)
metrics.values[2] = fmt.Sprintf("%d", time.Now().UnixMilli())
// custom labels via -l label=value
for idx, label := range conf.Labels {
metrics.values[idx+LabelLen] = label.Value
}
switch {
case conf.ReadMode && conf.WriteMode:
metrics.mode = O_RW
case conf.ReadMode:
metrics.mode = O_R
case conf.WriteMode:
metrics.mode = O_W
}
return metrics
}
func (metrics *Metrics) Set(result_r, result_w Result) {
var res float64
switch metrics.mode {
case O_RW:
if result_r.result && result_w.result {
res = 1
}
case O_R:
if result_r.result {
res = 1
}
case O_W:
if result_w.result {
res = 1
}
}
metrics.run.WithLabelValues(metrics.values...).Set(res)
metrics.latency_r.WithLabelValues(metrics.values...).Set(result_r.elapsed)
metrics.latency_w.WithLabelValues(metrics.values...).Set(result_w.elapsed)
}