cc53c1a3e4
internal/transport/metrics.go: Metrics struct with counters/gauges, WritePrometheus text exposition; internal/cli/metrics.go: orca metrics HTTP server on :9100 serving /metrics + /healthz. No client_golang dep. ---ci--- project: orca phase: 01 milestone: v0.11 status: execute ---/ci---
127 lines
3.0 KiB
Go
127 lines
3.0 KiB
Go
package transport
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"net"
|
|
"net/http"
|
|
"strings"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestWritePrometheusFormat(t *testing.T) {
|
|
m := NewMetrics()
|
|
m.IncCounter("txns_applied_total")
|
|
m.AddCounter("txns_applied_total", 41)
|
|
m.SetGauge("peers_total", 5)
|
|
m.SetGauge("nodes_total", 3.5)
|
|
|
|
var sb strings.Builder
|
|
if err := m.WritePrometheus(&sb); err != nil {
|
|
t.Fatalf("WritePrometheus: %v", err)
|
|
}
|
|
out := sb.String()
|
|
|
|
want := []string{
|
|
"# HELP txns_applied_total Total transactions applied",
|
|
"# TYPE txns_applied_total counter",
|
|
"txns_applied_total 42",
|
|
"# HELP txns_drifted_total Total transactions drifted",
|
|
"# TYPE txns_drifted_total counter",
|
|
"txns_drifted_total 0",
|
|
"# HELP drifts_remediated_total Total drifts remediated",
|
|
"# TYPE drifts_remediated_total counter",
|
|
"drifts_remediated_total 0",
|
|
"# HELP peers_total Current peer count",
|
|
"# TYPE peers_total gauge",
|
|
"peers_total 5",
|
|
"# HELP nodes_total Current node count",
|
|
"# TYPE nodes_total gauge",
|
|
"nodes_total 3.5",
|
|
"# HELP allocs_total Current allocation count",
|
|
"# TYPE allocs_total gauge",
|
|
"allocs_total 0",
|
|
}
|
|
for _, w := range want {
|
|
if !strings.Contains(out, w+"\n") {
|
|
t.Errorf("output missing line %q\n--- got:\n%s", w, out)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMetricsConcurrent(t *testing.T) {
|
|
m := NewMetrics()
|
|
var wg sync.WaitGroup
|
|
for i := 0; i < 100; i++ {
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
m.IncCounter("txns_applied_total")
|
|
m.SetGauge("peers_total", 1)
|
|
}()
|
|
}
|
|
wg.Wait()
|
|
var sb strings.Builder
|
|
if err := m.WritePrometheus(&sb); err != nil {
|
|
t.Fatalf("WritePrometheus: %v", err)
|
|
}
|
|
if !strings.Contains(sb.String(), "txns_applied_total 100\n") {
|
|
t.Errorf("expected 100 applied, got:\n%s", sb.String())
|
|
}
|
|
}
|
|
|
|
func TestMetricsHTTP(t *testing.T) {
|
|
m := NewMetrics()
|
|
m.IncCounter("txns_applied_total")
|
|
m.SetGauge("nodes_total", 7)
|
|
|
|
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
|
if err != nil {
|
|
t.Fatalf("listen: %v", err)
|
|
}
|
|
addr := ln.Addr().String()
|
|
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("/metrics", func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "text/plain; version=0.0.4; charset=utf-8")
|
|
_ = m.WritePrometheus(w)
|
|
})
|
|
srv := &http.Server{Handler: mux}
|
|
|
|
go srv.Serve(ln)
|
|
defer srv.Shutdown(context.Background())
|
|
|
|
time.Sleep(20 * time.Millisecond)
|
|
|
|
resp, err := http.Get("http://" + addr + "/metrics")
|
|
if err != nil {
|
|
t.Fatalf("GET /metrics: %v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
t.Fatalf("read body: %v", err)
|
|
}
|
|
s := string(body)
|
|
for _, name := range []string{
|
|
"txns_applied_total",
|
|
"txns_drifted_total",
|
|
"drifts_remediated_total",
|
|
"peers_total",
|
|
"nodes_total",
|
|
"allocs_total",
|
|
} {
|
|
if !strings.Contains(s, name) {
|
|
t.Errorf("response missing metric %q", name)
|
|
}
|
|
}
|
|
if !strings.Contains(s, "txns_applied_total 1\n") {
|
|
t.Errorf("counter value wrong in:\n%s", s)
|
|
}
|
|
if !strings.Contains(s, "nodes_total 7\n") {
|
|
t.Errorf("gauge value wrong in:\n%s", s)
|
|
}
|
|
}
|