Ctrl K
ComunidadGuías…

series_counters_seeded_test.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package main

import (
	"os"
	"path/filepath"
	"regexp"
	"runtime"
	"sort"
	"strings"
	"testing"
)

// TestSeriesCountersAreSeededAndExported guards the two lists that have to move
// together whenever the chart-aggregate cache learns a new outcome, and which
// nothing else checks: seedKnownCounters in this file's package (main.go) and
// the named-family table in writeNamedStats (internal/web/web.go).
//
// The failure this exists to catch has already happened twice. A state is added
// to Store.Series, the store's own tests pass because they read the counter
// directly, and the two lists are left behind - so the new counter is absent
// from a scrape until its first increment (unseeded counters spring into
// existence at 1, which rate() and increase() cannot see across that boundary)
// and, if it is also missing from writeNamedStats, has no named family at all.
// The visible symptom is a scrape whose numbers do not reconcile: main.go's
// seeding comment states the relation the families are read against each other
// with, queries = outcomes - hits, and a missing member silently breaks it.
//
// Scanning the store's source rather than hardcoding the names is the point.
// A fixed list here would need the same manual update as the two lists it
// guards, and would therefore go stale in exactly the case the test exists for.
func TestSeriesCountersAreSeededAndExported(t *testing.T) {
	_, thisFile, ok := callerFile()
	if !ok {
		t.Fatal("runtime.Caller failed; cannot locate the module root")
	}
	root := filepath.Dir(thisFile) // this file lives at the module root

	read := func(rel string) string {
		b, err := os.ReadFile(filepath.Join(root, rel))
		if err != nil {
			t.Fatalf("read %s: %v", rel, err)
		}
		return string(b)
	}

	// Every stats.Inc("series...") the store records. The store is the only
	// producer: these counters describe its cache, and a counter incremented
	// anywhere else would not be part of the queries = outcomes - hits relation.
	storeSrc := read(filepath.Join("internal", "store", "store.go"))
	recorded := regexp.MustCompile(`stats\.Inc\("(series\.[a-z.]+)"\)`).FindAllStringSubmatch(storeSrc, -1)
	if len(recorded) == 0 {
		t.Fatal("no stats.Inc(\"series.*\") calls found in internal/store/store.go: " +
			"either the counters were removed, or the call shape changed and this guard now " +
			"scans for something that no longer exists, which would let it pass vacuously")
	}

	seen := map[string]bool{}
	var keys []string
	for _, m := range recorded {
		if !seen[m[1]] {
			seen[m[1]] = true
			keys = append(keys, m[1])
		}
	}
	sort.Strings(keys)

	mainSrc := read("main.go")
	webSrc := read(filepath.Join("internal", "web", "web.go"))
	for _, k := range keys {
		quoted := `"` + k + `"`
		if !strings.Contains(mainSrc, quoted) {
			t.Errorf("internal/store records %s but main.go never names it: an unseeded counter is "+
				"absent from /metrics until its first increment, so its family appears mid-series and "+
				"rate() cannot see the step. Add it to seedKnownCounters.", k)
		}
		if !strings.Contains(webSrc, quoted) {
			t.Errorf("internal/store records %s but internal/web/web.go never names it: with no entry "+
				"in writeNamedStats it has no pingularity_series_* family, so a scrape carries a query "+
				"count its outcome counters cannot account for. Add it to the named-family table.", k)
		}
	}
}

// callerFile isolates the runtime.Caller call so the test body reads plainly.
func callerFile() (uintptr, string, bool) {
	pc, file, _, ok := runtime.Caller(1)
	return pc, file, ok
}