85 lines
2.5 KiB
Go
85 lines
2.5 KiB
Go
package metrics
|
|
|
|
import (
|
|
"net/http/httptest"
|
|
"strings"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestHandlerUsesOnlyFixedLowCardinalityLabels(t *testing.T) {
|
|
t.Parallel()
|
|
registry := New("ins_test-1", "v-test")
|
|
registry.ObserveReconcileRun(nil, 1500*time.Millisecond)
|
|
registry.ObserveReconcileItem("success")
|
|
registry.ObserveReconcileItem("lease_lost")
|
|
registry.SetConvergence(16, 2)
|
|
registry.ObserveOrphanScan(20, 1, 3, nil)
|
|
registry.ObserveOrphanCleanupBlocked("ratio_exceeded")
|
|
registry.ObserveOrphanCleanup(1, 1)
|
|
|
|
request := httptest.NewRequest("GET", "/metrics", nil)
|
|
response := httptest.NewRecorder()
|
|
registry.Handler().ServeHTTP(response, request)
|
|
body := response.Body.String()
|
|
for _, expected := range []string{
|
|
`sense_build_info{instance_id="ins_test-1",version="v-test"} 1`,
|
|
`sense_reconcile_items_total{result="lease_lost"} 1`,
|
|
`sense_reconcile_devices{state="unconverged"} 2`,
|
|
`sense_orphan_paths{classification="owned_stale"} 1`,
|
|
`sense_orphan_cleanup_blocked_total{reason="ratio_exceeded"} 1`,
|
|
} {
|
|
if !strings.Contains(body, expected) {
|
|
t.Fatalf("metrics output lacks %q:\n%s", expected, body)
|
|
}
|
|
}
|
|
for _, forbidden := range []string{
|
|
"tenant_id", "site_id", "device_id", "path_name", "rtsp://", "credential",
|
|
} {
|
|
if strings.Contains(body, forbidden) {
|
|
t.Fatalf("high-cardinality or secret-bearing label appeared: %q", forbidden)
|
|
}
|
|
}
|
|
if response.Header().Get("Cache-Control") != "no-store" {
|
|
t.Fatal("metrics responses must not be cached")
|
|
}
|
|
}
|
|
|
|
func TestRegistryIsSafeForConcurrentObservers(t *testing.T) {
|
|
t.Parallel()
|
|
registry := New("ins_concurrent", "dev")
|
|
var wait sync.WaitGroup
|
|
for index := 0; index < 32; index++ {
|
|
wait.Add(1)
|
|
go func() {
|
|
defer wait.Done()
|
|
for count := 0; count < 100; count++ {
|
|
registry.ObserveReconcileItem("success")
|
|
registry.SetConvergence(128, count%17)
|
|
}
|
|
}()
|
|
}
|
|
wait.Wait()
|
|
response := httptest.NewRecorder()
|
|
registry.Handler().ServeHTTP(response, httptest.NewRequest("GET", "/metrics", nil))
|
|
if !strings.Contains(response.Body.String(), `sense_reconcile_items_total{result="success"} 3200`) {
|
|
t.Fatalf("concurrent counter lost updates: %s", response.Body.String())
|
|
}
|
|
}
|
|
|
|
func TestGenerateInstanceIDShape(t *testing.T) {
|
|
t.Parallel()
|
|
first, err := GenerateInstanceID()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
second, err := GenerateInstanceID()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(first) != 28 || !strings.HasPrefix(first, "ins_") || first == second {
|
|
t.Fatalf("unexpected instance identifiers: %q %q", first, second)
|
|
}
|
|
}
|