Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add default Go runtime metrics for /gc/gogc:percent, /gc/gomemlimit:bytes, /sched/gomaxprocs:threads #1559

Merged
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions prometheus/collectors/go_collector_go117_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
17 changes: 17 additions & 0 deletions prometheus/collectors/go_collector_go119_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package collectors

import "sort"

func withAllMetrics() []string {
return withBaseMetrics([]string{
"go_cgo_go_to_c_calls_calls_total",
Expand Down Expand Up @@ -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
}
17 changes: 17 additions & 0 deletions prometheus/collectors/go_collector_go120_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package collectors

import "sort"

func withAllMetrics() []string {
return withBaseMetrics([]string{
"go_cgo_go_to_c_calls_calls_total",
Expand Down Expand Up @@ -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".
bwplotka marked this conversation as resolved.
Show resolved Hide resolved
if withoutSched {
return metricNames
}
metricNames = append(metricNames, defaultRuntimeMetrics...)
// sorting is required
sort.Strings(metricNames)
return metricNames
}
27 changes: 27 additions & 0 deletions prometheus/collectors/go_collector_go121_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package collectors

import "sort"

func withAllMetrics() []string {
return withBaseMetrics([]string{
"go_cgo_go_to_c_calls_calls_total",
Expand Down Expand Up @@ -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
}
27 changes: 27 additions & 0 deletions prometheus/collectors/go_collector_go122_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package collectors

import "sort"

func withAllMetrics() []string {
return withBaseMetrics([]string{
"go_cgo_go_to_c_calls_calls_total",
Expand Down Expand Up @@ -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
}
28 changes: 19 additions & 9 deletions prometheus/collectors/go_collector_latest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand All @@ -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)
}
}
Expand All @@ -127,7 +129,7 @@ func TestGoCollectorAllowList(t *testing.T) {
{
name: "Without any rules",
rules: nil,
expected: baseMetrics,
expected: withBaseMetrics(defaultRuntimeMetrics),
},
{
name: "allow all",
Expand 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) {
Expand Down Expand Up @@ -193,7 +195,7 @@ func TestGoCollectorDenyList(t *testing.T) {
{
name: "Without any matchers",
matchers: nil,
expected: baseMetrics,
expected: withBaseMetrics(defaultRuntimeMetrics),
},
{
name: "deny all",
Expand 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,
},
} {
Expand Down Expand Up @@ -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{}))
Expand Down
42 changes: 33 additions & 9 deletions prometheus/gen_go_collector_metrics_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,29 @@ func main() {
v := goVersion(gv.Segments()[1])
log.Printf("generating metrics for Go version %q", v)

allDesc := metrics.All()

// Find default metrics.
var defaultDesc []metrics.Description
for _, d := range allDesc {
if !internal.GoCollectorDefaultRuntimeMetrics.MatchString(d.Name) {
continue
}
defaultDesc = append(defaultDesc, d)
}

// Generate code.
var buf bytes.Buffer
err = testFile.Execute(&buf, struct {
Descriptions []metrics.Description
GoVersion goVersion
Cardinality int
AllDescriptions []metrics.Description
DefaultDescriptions []metrics.Description
GoVersion goVersion
Cardinality int
}{
Descriptions: metrics.All(),
GoVersion: v,
Cardinality: rmCardinality(),
AllDescriptions: allDesc,
DefaultDescriptions: defaultDesc,
GoVersion: v,
Cardinality: rmCardinality(),
})
if err != nil {
log.Fatalf("executing template: %v", err)
Expand Down Expand Up @@ -167,14 +180,25 @@ var testFile = template.Must(template.New("testFile").Funcs(map[string]interface

package prometheus

var expectedRuntimeMetrics = map[string]string{
{{- range .Descriptions -}}
var (
expectedRuntimeMetrics = map[string]string{
{{- range .AllDescriptions -}}
{{- $trans := rm2prom . -}}
{{- if ne $trans "" }}
{{.Name | printf "%q"}}: {{$trans | printf "%q"}},
{{- end -}}
{{end}}
}
}

expMetrics = map[string]string{
{{- range .DefaultDescriptions -}}
{{- $trans := rm2prom . -}}
{{- if ne $trans "" }}
{{.Name | printf "%q"}}: {{$trans | printf "%q"}},
{{- end -}}
{{end}}
}
)

const expectedRuntimeMetricsCardinality = {{.Cardinality}}
`))
8 changes: 5 additions & 3 deletions prometheus/go_collector_latest.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package prometheus

import (
"fmt"
"math"
"runtime"
"runtime/metrics"
Expand Down Expand Up @@ -153,7 +154,8 @@ func defaultGoCollectorOptions() internal.GoCollectorOptions {
"/gc/heap/frees-by-size:bytes": goGCHeapFreesBytes,
},
RuntimeMetricRules: []internal.GoCollectorRule{
//{Matcher: regexp.MustCompile("")},
// Recommended metrics we want by default from runtime/metrics.
{Matcher: internal.GoCollectorDefaultRuntimeMetrics},
},
}
}
Expand Down Expand Up @@ -376,13 +378,13 @@ func unwrapScalarRMValue(v metrics.Value) float64 {
//
// This should never happen because we always populate our metric
// set from the runtime/metrics package.
panic("unexpected unsupported metric")
panic("unexpected bad kind metric")
default:
// Unsupported metric kind.
//
// This should never happen because we check for this during initialization
// and flag and filter metrics whose kinds we don't understand.
panic("unexpected unsupported metric kind")
panic(fmt.Sprintf("unexpected unsupported metric: %v", v.Kind()))
}
}

Expand Down
16 changes: 14 additions & 2 deletions prometheus/go_collector_latest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ func addExpectedRuntimeMetrics(metrics map[string]struct{}) map[string]struct{}
return metrics
}

func addExpectedDefaultRuntimeMetrics(metrics map[string]struct{}) map[string]struct{} {
for _, e := range expMetrics {
metrics[e] = struct{}{}
}
return metrics
}

func TestGoCollector_ExposedMetrics(t *testing.T) {
for _, tcase := range []struct {
opts internal.GoCollectorOptions
Expand All @@ -86,8 +93,13 @@ func TestGoCollector_ExposedMetrics(t *testing.T) {
expectedFQNameSet: expectedBaseMetrics(),
},
{
// Default, only MemStats.
expectedFQNameSet: addExpectedRuntimeMemStats(expectedBaseMetrics()),
// Default, only MemStats and default Runtime metrics.
opts: internal.GoCollectorOptions{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's use default function then?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mind using our new internal.GoCollector default etc here?

RuntimeMetricRules: []internal.GoCollectorRule{
{Matcher: regexp.MustCompile(`\/gc\/gogc:percent|\/gc\/gomemlimit:bytes|\/sched\/gomaxprocs:threads`)},
},
},
expectedFQNameSet: addExpectedDefaultRuntimeMetrics(addExpectedRuntimeMemStats(expectedBaseMetrics())),
},
{
// Get all runtime/metrics without MemStats.
Expand Down
Loading