tsweb/varz: export GC CPU fraction gauge

We were missing this metric, but it can be important for some workloads.

Varz memstats output allocation cost reduced from 30 allocs per
invocation to 1 alloc per invocation.

Updates tailscale/corp#28033

Signed-off-by: James Tucker <james@tailscale.com>
Co-authored-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
James Tucker
2025-04-28 09:04:02 -07:00
committed by James Tucker
parent 189e03e741
commit b95e8bf4a1
5 changed files with 128 additions and 17 deletions
+75
View File
@@ -4,14 +4,17 @@
package varz
import (
"bytes"
"expvar"
"net/http/httptest"
"reflect"
"runtime"
"strings"
"testing"
"tailscale.com/metrics"
"tailscale.com/tstest"
"tailscale.com/util/racebuild"
"tailscale.com/version"
)
@@ -418,3 +421,75 @@ func TestVarzHandlerSorting(t *testing.T) {
}
}
}
func TestWriteMemestats(t *testing.T) {
memstats := &runtime.MemStats{
Alloc: 1,
TotalAlloc: 2,
Sys: 3,
Lookups: 4,
Mallocs: 5,
Frees: 6,
HeapAlloc: 7,
HeapSys: 8,
HeapIdle: 9,
HeapInuse: 10,
HeapReleased: 11,
HeapObjects: 12,
StackInuse: 13,
StackSys: 14,
MSpanInuse: 15,
MSpanSys: 16,
MCacheInuse: 17,
MCacheSys: 18,
BuckHashSys: 19,
GCSys: 20,
OtherSys: 21,
NextGC: 22,
LastGC: 23,
PauseTotalNs: 24,
// PauseNs: [256]int64{},
NumGC: 26,
NumForcedGC: 27,
GCCPUFraction: 0.28,
}
var buf bytes.Buffer
writeMemstats(&buf, memstats)
lines := strings.Split(buf.String(), "\n")
checkFor := func(name, typ, value string) {
var foundType, foundValue bool
for _, line := range lines {
if line == "memstats_"+name+" "+value {
foundValue = true
}
if line == "# TYPE memstats_"+name+" "+typ {
foundType = true
}
if foundValue && foundType {
return
}
}
t.Errorf("memstats_%s foundType=%v foundValue=%v", name, foundType, foundValue)
}
t.Logf("memstats:\n %s", buf.String())
checkFor("heap_alloc", "gauge", "7")
checkFor("total_alloc", "counter", "2")
checkFor("sys", "gauge", "3")
checkFor("mallocs", "counter", "5")
checkFor("frees", "counter", "6")
checkFor("num_gc", "counter", "26")
checkFor("gc_cpu_fraction", "gauge", "0.28")
if !racebuild.On {
if allocs := testing.AllocsPerRun(1000, func() {
buf.Reset()
writeMemstats(&buf, memstats)
}); allocs != 1 {
t.Errorf("allocs = %v; want max %v", allocs, 1)
}
}
}