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 12 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
10 changes: 7 additions & 3 deletions prometheus/go_collector_latest.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
package prometheus

import (
"fmt"
"math"
"regexp"
"runtime"
"runtime/metrics"
"strings"
Expand Down Expand Up @@ -153,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`),
Copy link
Member

Choose a reason for hiding this comment

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

hm, do we really need to escape /? It's not sed, it's RE2 language 🤔

},
},
}
}
Expand Down Expand Up @@ -376,13 +380,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
21 changes: 21 additions & 0 deletions prometheus/go_collector_latest_go120_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// 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

var expMetrics = map[string]string{
bwplotka marked this conversation as resolved.
Show resolved Hide resolved
"/sched/gomaxprocs:threads": "go_sched_gomaxprocs_threads",
}
23 changes: 23 additions & 0 deletions prometheus/go_collector_latest_go121_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// 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

var 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",
}
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