Move default runtime metrics into the runtime metrics flow, change tests accordingly

Signed-off-by: Arianna Vespri <arianna.vespri@yahoo.it>
This commit is contained in:
Arianna Vespri 2024-08-06 16:44:57 +02:00
parent a04c89174c
commit 20ebd6ccd2
13 changed files with 148 additions and 180 deletions

View File

@ -102,3 +102,9 @@ func withSchedulerMetrics() []string {
func withDebugMetrics() []string {
return withBaseMetrics([]string{})
}
var defaultRuntimeMetrics = []string{}
func withDefaultRuntimeMetrics(metricNames []string, withoutGC, withoutSched bool) []string {
return metricNames
}

View File

@ -16,6 +16,8 @@
package collectors
import "sort"
func withAllMetrics() []string {
return withBaseMetrics([]string{
"go_cgo_go_to_c_calls_calls_total",
@ -109,3 +111,18 @@ func withSchedulerMetrics() []string {
func withDebugMetrics() []string {
return withBaseMetrics([]string{})
}
var defaultRuntimeMetrics = []string{
"go_sched_gomaxprocs_threads",
}
func withDefaultRuntimeMetrics(metricNames []string, withoutGC, withoutSched bool) []string {
// If withoutSched is true, exclude "go_sched_gomaxprocs_threads".
if withoutSched {
return metricNames
}
metricNames = append(metricNames, defaultRuntimeMetrics...)
// sorting is required
sort.Strings(metricNames)
return metricNames
}

View File

@ -16,6 +16,8 @@
package collectors
import "sort"
func withAllMetrics() []string {
return withBaseMetrics([]string{
"go_cgo_go_to_c_calls_calls_total",
@ -116,3 +118,18 @@ func withSchedulerMetrics() []string {
func withDebugMetrics() []string {
return withBaseMetrics([]string{})
}
var defaultRuntimeMetrics = []string{
"go_sched_gomaxprocs_threads",
}
func withDefaultRuntimeMetrics(metricNames []string, withoutGC, withoutSched bool) []string {
// If withoutSched is true, exclude "go_sched_gomaxprocs_threads".
if withoutSched {
return metricNames
}
metricNames = append(metricNames, defaultRuntimeMetrics...)
// sorting is required
sort.Strings(metricNames)
return metricNames
}

View File

@ -16,6 +16,8 @@
package collectors
import "sort"
func withAllMetrics() []string {
return withBaseMetrics([]string{
"go_cgo_go_to_c_calls_calls_total",
@ -169,3 +171,28 @@ func withDebugMetrics() []string {
"go_godebug_non_default_behavior_zipinsecurepath_events_total",
})
}
var defaultRuntimeMetrics = []string{
"go_gc_gogc_percent",
"go_gc_gomemlimit_bytes",
"go_sched_gomaxprocs_threads",
}
func withDefaultRuntimeMetrics(metricNames []string, withoutGC, withoutSched bool) []string {
if withoutGC && withoutSched {
// If both flags are true, return the metricNames as is.
return metricNames
} else if withoutGC && !withoutSched {
// If only withoutGC is true, include "go_sched_gomaxprocs_threads" only.
metricNames = append(metricNames, []string{"go_sched_gomaxprocs_threads"}...)
} else if withoutSched && !withoutGC {
// If only withoutSched is true, exclude "go_sched_gomaxprocs_threads".
metricNames = append(metricNames, []string{"go_gc_gogc_percent", "go_gc_gomemlimit_bytes"}...)
} else {
// If neither flag is true, use the default metrics.
metricNames = append(metricNames, defaultRuntimeMetrics...)
}
// sorting is required
sort.Strings(metricNames)
return metricNames
}

View File

@ -16,6 +16,8 @@
package collectors
import "sort"
func withAllMetrics() []string {
return withBaseMetrics([]string{
"go_cgo_go_to_c_calls_calls_total",
@ -191,3 +193,28 @@ func withDebugMetrics() []string {
"go_godebug_non_default_behavior_zipinsecurepath_events_total",
})
}
var defaultRuntimeMetrics = []string{
"go_gc_gogc_percent",
"go_gc_gomemlimit_bytes",
"go_sched_gomaxprocs_threads",
}
func withDefaultRuntimeMetrics(metricNames []string, withoutGC, withoutSched bool) []string {
if withoutGC && withoutSched {
// If both flags are true, return the metricNames as is.
return metricNames
} else if withoutGC && !withoutSched {
// If only withoutGC is true, include "go_sched_gomaxprocs_threads" only.
metricNames = append(metricNames, []string{"go_sched_gomaxprocs_threads"}...)
} else if withoutSched && !withoutGC {
// If only withoutSched is true, exclude "go_sched_gomaxprocs_threads".
metricNames = append(metricNames, []string{"go_gc_gogc_percent", "go_gc_gomemlimit_bytes"}...)
} else {
// If neither flag is true, use the default metrics.
metricNames = append(metricNames, defaultRuntimeMetrics...)
}
// sorting is required
sort.Strings(metricNames)
return metricNames
}

View File

@ -88,16 +88,6 @@ func WithGoCollectorMemStatsMetricsDisabled() func(options *internal.GoCollector
}
}
// WithGoCollectorRuntimeEnvVarsMetricsDisabled disables the following default metrics:
// go_gogc_percent
// go_gomemlimit
// go_gomaxprocs
func WithGoCollectorRuntimeEnvVarsMetricsDisabled() func(options *internal.GoCollectorOptions) {
return func(o *internal.GoCollectorOptions) {
o.DisableRuntimeEnvVarsMetrics = true
}
}
// GoRuntimeMetricsRule allow enabling and configuring particular group of runtime/metrics.
// TODO(bwplotka): Consider adding ability to adjust buckets.
type GoRuntimeMetricsRule struct {

View File

@ -93,7 +93,9 @@ func TestWithGoCollectorDefault(t *testing.T) {
got = append(got, r.GetName())
}
if diff := cmp.Diff(got, withBaseMetrics(memstatMetrics)); diff != "" {
expected := append(withBaseMetrics(memstatMetrics), defaultRuntimeMetrics...)
sort.Strings(expected)
if diff := cmp.Diff(got, expected); diff != "" {
t.Errorf("[IMPORTANT, those are default metrics, can't change in 1.x] missmatch (-want +got):\n%s", diff)
}
}
@ -113,7 +115,7 @@ func TestWithGoCollectorMemStatsMetricsDisabled(t *testing.T) {
got = append(got, r.GetName())
}
if diff := cmp.Diff(got, baseMetrics); diff != "" {
if diff := cmp.Diff(got, withBaseMetrics(defaultRuntimeMetrics)); diff != "" {
t.Errorf("missmatch (-want +got):\n%s", diff)
}
}
@ -127,7 +129,7 @@ func TestGoCollectorAllowList(t *testing.T) {
{
name: "Without any rules",
rules: nil,
expected: baseMetrics,
expected: withBaseMetrics(defaultRuntimeMetrics),
},
{
name: "allow all",
@ -137,22 +139,22 @@ func TestGoCollectorAllowList(t *testing.T) {
{
name: "allow GC",
rules: []GoRuntimeMetricsRule{MetricsGC},
expected: withGCMetrics(),
expected: withDefaultRuntimeMetrics(withGCMetrics(), true, false),
},
{
name: "allow Memory",
rules: []GoRuntimeMetricsRule{MetricsMemory},
expected: withMemoryMetrics(),
expected: withDefaultRuntimeMetrics(withMemoryMetrics(), false, false),
},
{
name: "allow Scheduler",
rules: []GoRuntimeMetricsRule{MetricsScheduler},
expected: withSchedulerMetrics(),
expected: withDefaultRuntimeMetrics(withSchedulerMetrics(), false, true),
},
{
name: "allow debug",
rules: []GoRuntimeMetricsRule{MetricsDebug},
expected: withDebugMetrics(),
expected: withDefaultRuntimeMetrics(withDebugMetrics(), false, false),
},
} {
t.Run(test.name, func(t *testing.T) {
@ -193,7 +195,7 @@ func TestGoCollectorDenyList(t *testing.T) {
{
name: "Without any matchers",
matchers: nil,
expected: baseMetrics,
expected: withBaseMetrics(defaultRuntimeMetrics),
},
{
name: "deny all",
@ -206,6 +208,14 @@ func TestGoCollectorDenyList(t *testing.T) {
regexp.MustCompile("^/gc/.*"),
regexp.MustCompile("^/sched/latencies:.*"),
},
expected: withDefaultRuntimeMetrics(baseMetrics, true, false),
},
{
name: "deny gc and scheduler",
matchers: []*regexp.Regexp{
regexp.MustCompile("^/gc/.*"),
regexp.MustCompile("^/sched/.*"),
},
expected: baseMetrics,
},
} {
@ -235,7 +245,7 @@ func TestGoCollectorDenyList(t *testing.T) {
func ExampleGoCollector() {
reg := prometheus.NewRegistry()
// Register the GoCollector with the default options. Only the base metrics and memstats are enabled.
// Register the GoCollector with the default options. Only the base metrics, default runtime metrics and memstats are enabled.
reg.MustRegister(NewGoCollector())
http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{}))

View File

@ -280,8 +280,3 @@ type memStatsMetrics []struct {
eval func(*runtime.MemStats) float64
valType ValueType
}
type runtimeEnvVarsMetrics []struct { // I couldn't come up with a better name. Any suggestions?
desc *Desc
origMetricName string
}

View File

@ -1,30 +0,0 @@
// Copyright 2024 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !go1.21
// +build !go1.21
package prometheus
func goRuntimeEnvVarsMetrics() runtimeEnvVarsMetrics {
return runtimeEnvVarsMetrics{
{
desc: NewDesc(
"go_gomaxprocs",
"Value of GOMAXPROCS, i.e number of usable threads.",
nil, nil,
),
origMetricName: "/sched/gomaxprocs:threads",
},
}
}

View File

@ -1,46 +0,0 @@
// Copyright 2024 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build go1.21
// +build go1.21
package prometheus
func goRuntimeEnvVarsMetrics() runtimeEnvVarsMetrics {
return runtimeEnvVarsMetrics{
{
desc: NewDesc(
"go_gogc_percent",
"Value of GOGC (percentage).",
nil, nil,
),
origMetricName: "/gc/gogc:percent",
},
{
desc: NewDesc(
"go_gomemlimit",
"Value of GOMEMLIMIT (bytes).",
nil, nil,
),
origMetricName: "/gc/gomemlimit:bytes",
},
{
desc: NewDesc(
"go_gomaxprocs",
"Value of GOMAXPROCS, i.e number of usable threads.",
nil, nil,
),
origMetricName: "/sched/gomaxprocs:threads",
},
}
}

View File

@ -19,6 +19,7 @@ package prometheus
import (
"fmt"
"math"
"regexp"
"runtime"
"runtime/metrics"
"strings"
@ -32,7 +33,6 @@ import (
const (
// constants for strings referenced more than once.
goGCGogcPercent = "/gc/gogc:percent"
goGCHeapTinyAllocsObjects = "/gc/heap/tiny/allocs:objects"
goGCHeapAllocsObjects = "/gc/heap/allocs:objects"
goGCHeapFreesObjects = "/gc/heap/frees:objects"
@ -40,7 +40,6 @@ const (
goGCHeapAllocsBytes = "/gc/heap/allocs:bytes"
goGCHeapObjects = "/gc/heap/objects:objects"
goGCHeapGoalBytes = "/gc/heap/goal:bytes"
goGCMemLimit = "/gc/gomemlimit:bytes"
goMemoryClassesTotalBytes = "/memory/classes/total:bytes"
goMemoryClassesHeapObjectsBytes = "/memory/classes/heap/objects:bytes"
goMemoryClassesHeapUnusedBytes = "/memory/classes/heap/unused:bytes"
@ -55,7 +54,6 @@ const (
goMemoryClassesProfilingBucketsBytes = "/memory/classes/profiling/buckets:bytes"
goMemoryClassesMetadataOtherBytes = "/memory/classes/metadata/other:bytes"
goMemoryClassesOtherBytes = "/memory/classes/other:bytes"
goSchedMaxProcs = "/sched/gomaxprocs:threads"
)
// rmNamesForMemStatsMetrics represents runtime/metrics names required to populate goRuntimeMemStats from like logic.
@ -82,12 +80,6 @@ var rmNamesForMemStatsMetrics = []string{
goMemoryClassesOtherBytes,
}
var rmNamesForEnvVarsMetrics = []string{ // how to name this var???
goGCGogcPercent,
goGCMemLimit,
goSchedMaxProcs,
}
func bestEffortLookupRM(lookup []string) []metrics.Description {
ret := make([]metrics.Description, 0, len(lookup))
for _, rm := range metrics.All() {
@ -126,9 +118,6 @@ type goCollector struct {
// as well.
msMetrics memStatsMetrics
msMetricsEnabled bool
rmEnvVarsMetrics runtimeEnvVarsMetrics // how to call them???
rmEnvVarsMetricsEnabled bool
}
type rmMetricDesc struct {
@ -166,7 +155,9 @@ func defaultGoCollectorOptions() internal.GoCollectorOptions {
"/gc/heap/frees-by-size:bytes": goGCHeapFreesBytes,
},
RuntimeMetricRules: []internal.GoCollectorRule{
//{Matcher: regexp.MustCompile("")},
{
Matcher: regexp.MustCompile(`\/gc\/gogc:percent|\/gc\/gomemlimit:bytes|\/sched\/gomaxprocs:threads`),
},
},
}
}
@ -206,7 +197,7 @@ func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector {
metricSet := make([]collectorMetric, 0, len(exposedDescriptions))
// SampleBuf is used for reading from runtime/metrics.
// We are assuming the largest case to have stable pointers for sampleMap purposes.
sampleBuf := make([]metrics.Sample, 0, len(exposedDescriptions)+len(opt.RuntimeMetricSumForHist)+len(rmNamesForMemStatsMetrics)+len(rmNamesForEnvVarsMetrics))
sampleBuf := make([]metrics.Sample, 0, len(exposedDescriptions)+len(opt.RuntimeMetricSumForHist)+len(rmNamesForMemStatsMetrics))
sampleMap := make(map[string]*metrics.Sample, len(exposedDescriptions))
for _, d := range exposedDescriptions {
namespace, subsystem, name, ok := internal.RuntimeMetricsToProm(&d.Description)
@ -270,8 +261,6 @@ func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector {
var (
msMetrics memStatsMetrics
msDescriptions []metrics.Description
rmEnvVarsMetrics runtimeEnvVarsMetrics
rmEnvVarsDescriptions []metrics.Description
)
if !opt.DisableMemStatsLikeMetrics {
@ -288,19 +277,6 @@ func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector {
}
}
if !opt.DisableRuntimeEnvVarsMetrics {
rmEnvVarsMetrics = goRuntimeEnvVarsMetrics()
rmEnvVarsDescriptions = bestEffortLookupRM(rmNamesForEnvVarsMetrics)
// Check if metric was not exposed before and if not, add to sampleBuf.
for _, rnevDesc := range rmEnvVarsDescriptions {
if _, ok := sampleMap[rnevDesc.Name]; ok {
continue
}
sampleBuf = append(sampleBuf, metrics.Sample{Name: rnevDesc.Name})
sampleMap[rnevDesc.Name] = &sampleBuf[len(sampleBuf)-1]
}
}
return &goCollector{
base: newBaseGoCollector(),
sampleBuf: sampleBuf,
@ -309,8 +285,6 @@ func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector {
rmExactSumMapForHist: opt.RuntimeMetricSumForHist,
msMetrics: msMetrics,
msMetricsEnabled: !opt.DisableMemStatsLikeMetrics,
rmEnvVarsMetrics: rmEnvVarsMetrics,
rmEnvVarsMetricsEnabled: !opt.DisableRuntimeEnvVarsMetrics,
}
}
@ -390,17 +364,6 @@ func (c *goCollector) Collect(ch chan<- Metric) {
ch <- MustNewConstMetric(i.desc, i.valType, i.eval(&ms))
}
}
if c.rmEnvVarsMetricsEnabled {
sampleBuf := make([]metrics.Sample, len(c.rmEnvVarsMetrics))
for i, v := range c.rmEnvVarsMetrics {
sampleBuf[i].Name = v.origMetricName
}
metrics.Read(sampleBuf)
for i, v := range c.rmEnvVarsMetrics {
ch <- MustNewConstMetric(v.desc, GaugeValue, unwrapScalarRMValue(sampleBuf[i].Value))
}
}
}
// unwrapScalarRMValue unwraps a runtime/metrics value that is assumed

View File

@ -74,9 +74,14 @@ func addExpectedRuntimeMetrics(metrics map[string]struct{}) map[string]struct{}
return metrics
}
func addExpectedEnvVarsMetrics(metrics map[string]struct{}) map[string]struct{} {
for _, m := range goRuntimeEnvVarsMetrics() {
metrics[m.desc.fqName] = struct{}{}
func addExpectedDefaultRuntimeMetrics(metrics map[string]struct{}) map[string]struct{} {
expMetrics := map[string]string{
"/gc/gogc:percent": "go_gc_gogc_percent",
"/gc/gomemlimit:bytes": "go_gc_gomemlimit_bytes",
"/sched/gomaxprocs:threads": "go_sched_gomaxprocs_threads",
}
for _, e := range expMetrics {
metrics[e] = struct{}{}
}
return metrics
}
@ -89,26 +94,22 @@ func TestGoCollector_ExposedMetrics(t *testing.T) {
{
opts: internal.GoCollectorOptions{
DisableMemStatsLikeMetrics: true,
DisableRuntimeEnvVarsMetrics: true,
},
expectedFQNameSet: expectedBaseMetrics(),
},
{
// Default, only Memstats and RuntimeEnvVars.
expectedFQNameSet: addExpectedEnvVarsMetrics(addExpectedRuntimeMemStats(expectedBaseMetrics())),
},
{
// Only MemStats.
// Default, only MemStats and default Runtime metrics.
opts: internal.GoCollectorOptions{
DisableRuntimeEnvVarsMetrics: true,
RuntimeMetricRules: []internal.GoCollectorRule{
{Matcher: regexp.MustCompile(`\/gc\/gogc:percent|\/gc\/gomemlimit:bytes|\/sched\/gomaxprocs:threads`)},
},
expectedFQNameSet: addExpectedRuntimeMemStats(expectedBaseMetrics()),
},
expectedFQNameSet: addExpectedDefaultRuntimeMetrics(addExpectedRuntimeMemStats(expectedBaseMetrics())),
},
{
// Get all runtime/metrics without MemStats nor RuntimeEnvVars.
// Get all runtime/metrics without MemStats.
opts: internal.GoCollectorOptions{
DisableMemStatsLikeMetrics: true,
DisableRuntimeEnvVarsMetrics: true,
RuntimeMetricRules: []internal.GoCollectorRule{
{Matcher: regexp.MustCompile("/.*")},
},
@ -116,20 +117,13 @@ func TestGoCollector_ExposedMetrics(t *testing.T) {
expectedFQNameSet: addExpectedRuntimeMetrics(expectedBaseMetrics()),
},
{
// Get all runtime/metrics, MemStats and RuntimeEnvVars.
// Get all runtime/metrics and MemStats.
opts: internal.GoCollectorOptions{
RuntimeMetricRules: []internal.GoCollectorRule{
{Matcher: regexp.MustCompile("/.*")},
},
},
expectedFQNameSet: addExpectedEnvVarsMetrics(addExpectedRuntimeMemStats(addExpectedRuntimeMetrics(expectedBaseMetrics()))),
},
{
// Only RuntimeEnvVars.
opts: internal.GoCollectorOptions{
DisableMemStatsLikeMetrics: true,
},
expectedFQNameSet: addExpectedEnvVarsMetrics(expectedBaseMetrics()),
expectedFQNameSet: addExpectedRuntimeMemStats(addExpectedRuntimeMetrics(expectedBaseMetrics())),
},
} {
if ok := t.Run("", func(t *testing.T) {
@ -252,7 +246,6 @@ func collectGoMetrics(t *testing.T, opts internal.GoCollectorOptions) []Metric {
o.DisableMemStatsLikeMetrics = opts.DisableMemStatsLikeMetrics
o.RuntimeMetricSumForHist = opts.RuntimeMetricSumForHist
o.RuntimeMetricRules = opts.RuntimeMetricRules
o.DisableRuntimeEnvVarsMetrics = opts.DisableRuntimeEnvVarsMetrics
}).(*goCollector)
// Collect all metrics.

View File

@ -29,5 +29,4 @@ type GoCollectorOptions struct {
DisableMemStatsLikeMetrics bool
RuntimeMetricSumForHist map[string]string
RuntimeMetricRules []GoCollectorRule
DisableRuntimeEnvVarsMetrics bool
}