Files
storage-appliance/internal/monitoring/prometheus.go

61 lines
1.5 KiB
Go

package monitoring
import (
"context"
"fmt"
"strings"
)
// PrometheusExporter exports metrics in Prometheus format
type PrometheusExporter struct {
Collectors []Collector
}
func NewPrometheusExporter(collectors ...Collector) *PrometheusExporter {
return &PrometheusExporter{Collectors: collectors}
}
// Export collects all metrics and formats them as Prometheus text format
func (e *PrometheusExporter) Export(ctx context.Context) string {
var builder strings.Builder
allErrors := []string{}
for _, collector := range e.Collectors {
collection := collector.Collect(ctx)
allErrors = append(allErrors, collection.Errors...)
for _, metric := range collection.Metrics {
// Format: metric_name{label1="value1",label2="value2"} value
builder.WriteString(metric.Name)
if len(metric.Labels) > 0 {
builder.WriteString("{")
first := true
for k, v := range metric.Labels {
if !first {
builder.WriteString(",")
}
builder.WriteString(fmt.Sprintf(`%s="%s"`, k, escapeLabelValue(v)))
first = false
}
builder.WriteString("}")
}
builder.WriteString(fmt.Sprintf(" %v\n", metric.Value))
}
}
// Add error metrics if any
if len(allErrors) > 0 {
builder.WriteString(fmt.Sprintf("monitoring_collector_errors_total %d\n", len(allErrors)))
}
return builder.String()
}
func escapeLabelValue(v string) string {
v = strings.ReplaceAll(v, "\\", "\\\\")
v = strings.ReplaceAll(v, "\"", "\\\"")
v = strings.ReplaceAll(v, "\n", "\\n")
return v
}