go collector: add default metrics acceptance tests; adding more context to HELP (#1568)

* go collector: add default metrics acceptance tests; adding more context to HELP

The context and details for help were possible thanks to @vesari research, thanks for that!

Signed-off-by: bwplotka <bwplotka@gmail.com>

* Update prometheus/go_collector.go

Co-authored-by: Arianna Vespri <36129782+vesari@users.noreply.github.com>
Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>

---------

Signed-off-by: bwplotka <bwplotka@gmail.com>
Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
Co-authored-by: Arianna Vespri <36129782+vesari@users.noreply.github.com>
This commit is contained in:
Bartlomiej Plotka 2024-08-01 10:24:31 +02:00 committed by GitHub
parent 697372d81e
commit 0ce6d719bc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 53 additions and 9 deletions

View File

@ -38,6 +38,31 @@ var baseMetrics = []string{
"go_threads", "go_threads",
} }
var memstatMetrics = []string{
"go_memstats_alloc_bytes",
"go_memstats_alloc_bytes_total",
"go_memstats_buck_hash_sys_bytes",
"go_memstats_frees_total",
"go_memstats_gc_sys_bytes",
"go_memstats_heap_alloc_bytes",
"go_memstats_heap_idle_bytes",
"go_memstats_heap_inuse_bytes",
"go_memstats_heap_objects",
"go_memstats_heap_released_bytes",
"go_memstats_heap_sys_bytes",
"go_memstats_lookups_total",
"go_memstats_mallocs_total",
"go_memstats_mcache_inuse_bytes",
"go_memstats_mcache_sys_bytes",
"go_memstats_mspan_inuse_bytes",
"go_memstats_mspan_sys_bytes",
"go_memstats_next_gc_bytes",
"go_memstats_other_sys_bytes",
"go_memstats_stack_inuse_bytes",
"go_memstats_stack_sys_bytes",
"go_memstats_sys_bytes",
}
func TestGoCollectorMarshalling(t *testing.T) { func TestGoCollectorMarshalling(t *testing.T) {
reg := prometheus.NewRegistry() reg := prometheus.NewRegistry()
reg.MustRegister(NewGoCollector( reg.MustRegister(NewGoCollector(
@ -55,6 +80,24 @@ func TestGoCollectorMarshalling(t *testing.T) {
} }
} }
func TestWithGoCollectorDefault(t *testing.T) {
reg := prometheus.NewRegistry()
reg.MustRegister(NewGoCollector())
result, err := reg.Gather()
if err != nil {
t.Fatal(err)
}
got := []string{}
for _, r := range result {
got = append(got, r.GetName())
}
if diff := cmp.Diff(got, withBaseMetrics(memstatMetrics)); diff != "" {
t.Errorf("[IMPORTANT, those are default metrics, can't change in 1.x] missmatch (-want +got):\n%s", diff)
}
}
func TestWithGoCollectorMemStatsMetricsDisabled(t *testing.T) { func TestWithGoCollectorMemStatsMetricsDisabled(t *testing.T) {
reg := prometheus.NewRegistry() reg := prometheus.NewRegistry()
reg.MustRegister(NewGoCollector( reg.MustRegister(NewGoCollector(
@ -192,7 +235,7 @@ func TestGoCollectorDenyList(t *testing.T) {
func ExampleGoCollector() { func ExampleGoCollector() {
reg := prometheus.NewRegistry() reg := prometheus.NewRegistry()
// Register the GoCollector with the default options. Only the base metrics will be enabled. // Register the GoCollector with the default options. Only the base metrics and memstats are enabled.
reg.MustRegister(NewGoCollector()) reg.MustRegister(NewGoCollector())
http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{})) http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{}))

View File

@ -22,13 +22,13 @@ import (
// goRuntimeMemStats provides the metrics initially provided by runtime.ReadMemStats. // goRuntimeMemStats provides the metrics initially provided by runtime.ReadMemStats.
// From Go 1.17 those similar (and better) statistics are provided by runtime/metrics, so // From Go 1.17 those similar (and better) statistics are provided by runtime/metrics, so
// while eval closure works on runtime.MemStats, the struct from Go 1.17+ is // while eval closure works on runtime.MemStats, the struct from Go 1.17+ is
// populated using runtime/metrics. // populated using runtime/metrics. Those are the defaults we can't alter.
func goRuntimeMemStats() memStatsMetrics { func goRuntimeMemStats() memStatsMetrics {
return memStatsMetrics{ return memStatsMetrics{
{ {
desc: NewDesc( desc: NewDesc(
memstatNamespace("alloc_bytes"), memstatNamespace("alloc_bytes"),
"Number of bytes allocated and still in use.", "Number of bytes allocated and currently in use.",
nil, nil, nil, nil,
), ),
eval: func(ms *runtime.MemStats) float64 { return float64(ms.Alloc) }, eval: func(ms *runtime.MemStats) float64 { return float64(ms.Alloc) },
@ -36,7 +36,7 @@ func goRuntimeMemStats() memStatsMetrics {
}, { }, {
desc: NewDesc( desc: NewDesc(
memstatNamespace("alloc_bytes_total"), memstatNamespace("alloc_bytes_total"),
"Total number of bytes allocated, even if freed.", "Total number of bytes allocated until now, even if released already.",
nil, nil, nil, nil,
), ),
eval: func(ms *runtime.MemStats) float64 { return float64(ms.TotalAlloc) }, eval: func(ms *runtime.MemStats) float64 { return float64(ms.TotalAlloc) },
@ -60,7 +60,8 @@ func goRuntimeMemStats() memStatsMetrics {
}, { }, {
desc: NewDesc( desc: NewDesc(
memstatNamespace("mallocs_total"), memstatNamespace("mallocs_total"),
"Total number of mallocs.", // TODO(bwplotka): We could add go_memstats_heap_objects, probably useful for discovery. Let's gather more feedback, kind of waste of bytes for everybody for compatibility reason.
"Total number of heap objects allocated, both live and gc-ed. Semantically a counter version for go_memstats_heap_objects gauge.",
nil, nil, nil, nil,
), ),
eval: func(ms *runtime.MemStats) float64 { return float64(ms.Mallocs) }, eval: func(ms *runtime.MemStats) float64 { return float64(ms.Mallocs) },
@ -68,7 +69,7 @@ func goRuntimeMemStats() memStatsMetrics {
}, { }, {
desc: NewDesc( desc: NewDesc(
memstatNamespace("frees_total"), memstatNamespace("frees_total"),
"Total number of frees.", "Total number of heap objects frees.",
nil, nil, nil, nil,
), ),
eval: func(ms *runtime.MemStats) float64 { return float64(ms.Frees) }, eval: func(ms *runtime.MemStats) float64 { return float64(ms.Frees) },
@ -76,7 +77,7 @@ func goRuntimeMemStats() memStatsMetrics {
}, { }, {
desc: NewDesc( desc: NewDesc(
memstatNamespace("heap_alloc_bytes"), memstatNamespace("heap_alloc_bytes"),
"Number of heap bytes allocated and still in use.", "Number of heap bytes allocated and currently in use.",
nil, nil, nil, nil,
), ),
eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapAlloc) }, eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapAlloc) },
@ -116,7 +117,7 @@ func goRuntimeMemStats() memStatsMetrics {
}, { }, {
desc: NewDesc( desc: NewDesc(
memstatNamespace("heap_objects"), memstatNamespace("heap_objects"),
"Number of allocated objects.", "Number of currently allocated objects.",
nil, nil, nil, nil,
), ),
eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapObjects) }, eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapObjects) },
@ -225,7 +226,7 @@ func newBaseGoCollector() baseGoCollector {
nil, nil), nil, nil),
gcDesc: NewDesc( gcDesc: NewDesc(
"go_gc_duration_seconds", "go_gc_duration_seconds",
"A summary of the pause duration of garbage collection cycles.", "A summary of the wall-time pause (stop-the-world) duration in garbage collection cycles.",
nil, nil), nil, nil),
gcLastTimeDesc: NewDesc( gcLastTimeDesc: NewDesc(
"go_memstats_last_gc_time_seconds", "go_memstats_last_gc_time_seconds",