Skip to content

Commit d0d127a

Browse files
committed
goCollector: Added rule support for granular metric configuration.
Fixes: #1089 Signed-off-by: bwplotka <bwplotka@gmail.com>
1 parent c7488be commit d0d127a

File tree

6 files changed

+320
-182
lines changed

6 files changed

+320
-182
lines changed

prometheus/collectors/go_collector_latest.go

Lines changed: 88 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -16,77 +16,102 @@
1616

1717
package collectors
1818

19-
import "github.com/prometheus/client_golang/prometheus"
19+
import (
20+
"regexp"
2021

21-
//nolint:staticcheck // Ignore SA1019 until v2.
22-
type goOptions = prometheus.GoCollectorOptions
23-
type goOption func(o *goOptions)
24-
25-
type GoCollectionOption uint32
26-
27-
const (
28-
// GoRuntimeMemStatsCollection represents the metrics represented by runtime.MemStats structure such as
29-
// go_memstats_alloc_bytes
30-
// go_memstats_alloc_bytes_total
31-
// go_memstats_sys_bytes
32-
// go_memstats_lookups_total
33-
// go_memstats_mallocs_total
34-
// go_memstats_frees_total
35-
// go_memstats_heap_alloc_bytes
36-
// go_memstats_heap_sys_bytes
37-
// go_memstats_heap_idle_bytes
38-
// go_memstats_heap_inuse_bytes
39-
// go_memstats_heap_released_bytes
40-
// go_memstats_heap_objects
41-
// go_memstats_stack_inuse_bytes
42-
// go_memstats_stack_sys_bytes
43-
// go_memstats_mspan_inuse_bytes
44-
// go_memstats_mspan_sys_bytes
45-
// go_memstats_mcache_inuse_bytes
46-
// go_memstats_mcache_sys_bytes
47-
// go_memstats_buck_hash_sys_bytes
48-
// go_memstats_gc_sys_bytes
49-
// go_memstats_other_sys_bytes
50-
// go_memstats_next_gc_bytes
51-
// so the metrics known from pre client_golang v1.12.0, except skipped go_memstats_gc_cpu_fraction (see
52-
// https://github.com/prometheus/client_golang/issues/842#issuecomment-861812034 for explanation.
53-
//
54-
// NOTE that this mode represents runtime.MemStats statistics, but they are
55-
// actually implemented using new runtime/metrics package.
56-
// Deprecated: Use GoRuntimeMetricsCollection instead going forward.
57-
GoRuntimeMemStatsCollection GoCollectionOption = 1 << iota
58-
// GoRuntimeMetricsCollection is the new set of metrics represented by runtime/metrics package and follows
59-
// consistent naming. The exposed metric set depends on Go version, but it is controlled against
60-
// unexpected cardinality. This set has overlapping information with GoRuntimeMemStatsCollection, just with
61-
// new names. GoRuntimeMetricsCollection is what is recommended for using going forward.
62-
GoRuntimeMetricsCollection
22+
"github.com/prometheus/client_golang/prometheus"
23+
"github.com/prometheus/client_golang/prometheus/internal"
6324
)
6425

65-
// WithGoCollections allows enabling different collections for Go collector on top of base metrics
66-
// like go_goroutines, go_threads, go_gc_duration_seconds, go_memstats_last_gc_time_seconds, go_info.
26+
// WithGoCollectorMemStatsMetricsDisabled metrics that where representing runtime.MemStats structure such as:
27+
//
28+
// go_memstats_alloc_bytes
29+
// go_memstats_alloc_bytes_total
30+
// go_memstats_sys_bytes
31+
// go_memstats_lookups_total
32+
// go_memstats_mallocs_total
33+
// go_memstats_frees_total
34+
// go_memstats_heap_alloc_bytes
35+
// go_memstats_heap_sys_bytes
36+
// go_memstats_heap_idle_bytes
37+
// go_memstats_heap_inuse_bytes
38+
// go_memstats_heap_released_bytes
39+
// go_memstats_heap_objects
40+
// go_memstats_stack_inuse_bytes
41+
// go_memstats_stack_sys_bytes
42+
// go_memstats_mspan_inuse_bytes
43+
// go_memstats_mspan_sys_bytes
44+
// go_memstats_mcache_inuse_bytes
45+
// go_memstats_mcache_sys_bytes
46+
// go_memstats_buck_hash_sys_bytes
47+
// go_memstats_gc_sys_bytes
48+
// go_memstats_other_sys_bytes
49+
// go_memstats_next_gc_bytes
50+
//
51+
// so the metrics known from pre client_golang v1.12.0,
52+
//
53+
// NOTE(bwplotka): The above represents runtime.MemStats statistics, but they are
54+
// actually implemented using new runtime/metrics package. (except skipped go_memstats_gc_cpu_fraction
55+
// -- see https://github.com/prometheus/client_golang/issues/842#issuecomment-861812034 for explanation).
6756
//
68-
// Check GoRuntimeMemStatsCollection and GoRuntimeMetricsCollection for more details. You can use none,
69-
// one or more collections at once. For example:
70-
// WithGoCollections(GoRuntimeMemStatsCollection | GoRuntimeMetricsCollection) means both GoRuntimeMemStatsCollection
71-
// metrics and GoRuntimeMetricsCollection will be exposed.
57+
// Some users might want to disable this on collector level (although you can use scrape relabelling on Prometheus),
58+
// because similar metrics can be now obtained using WithGoCollectorRuntimeMetrics. Note that the semantics of new
59+
// metrics might be different, plus the names can be change over time with different Go version.
7260
//
73-
// The current default is GoRuntimeMemStatsCollection, so the compatibility mode with
74-
// client_golang pre v1.12 (move to runtime/metrics).
75-
//nolint:staticcheck // Ignore SA1019 until v2.
76-
func WithGoCollections(flags GoCollectionOption) func(options *prometheus.GoCollectorOptions) {
77-
return func(o *goOptions) {
78-
o.EnabledCollections = uint32(flags)
61+
// NOTE(bwplotka): Changing metric names can be tedious at times as the alerts, recording rules and dashboards have to be adjusted.
62+
// The old metrics are also very useful, with many guides and books written about how to interpret them.
63+
//
64+
// As a result our recommendation would be to stick with MemStats like metrics and enable other runtime/metrics if you are interested
65+
// in advanced insights Go provides. See ExampleGoCollector_WithAdvancedGoMetrics.
66+
func WithGoCollectorMemStatsMetricsDisabled() func(options *internal.GoCollectorOptions) {
67+
return func(o *internal.GoCollectorOptions) {
68+
o.DisableMemStatsLikeMetrics = true
7969
}
8070
}
8171

82-
// NewGoCollector returns a collector that exports metrics about the current Go
83-
// process using debug.GCStats using runtime/metrics.
84-
func NewGoCollector(opts ...goOption) prometheus.Collector {
85-
//nolint:staticcheck // Ignore SA1019 until v2.
86-
promPkgOpts := make([]func(o *prometheus.GoCollectorOptions), len(opts))
87-
for i, opt := range opts {
88-
promPkgOpts[i] = opt
72+
// GoRuntimeMetricsRule allow enabling and configuring particular group of runtime/metrics.
73+
type GoRuntimeMetricsRule struct {
74+
// Matcher represents RE2 expression will match the runtime/metrics from https://golang.bg/src/runtime/metrics/description.go
75+
// Use `regexp.MustCompile` or `regexp.Compile` to create this field.
76+
Matcher *regexp.Regexp
77+
}
78+
79+
// WithGoCollectorRuntimeMetrics allows enabling and configuring particular group of runtime/metrics.
80+
// See the list of metrics https://golang.bg/src/runtime/metrics/description.go (pick the Go version you use there!).
81+
// You can use this option in repeated manner, which will add new rules. The order of rules is important, the last rule
82+
// that matches particular metrics is applied.
83+
func WithGoCollectorRuntimeMetrics(rules ...GoRuntimeMetricsRule) func(options *internal.GoCollectorOptions) {
84+
rs := make([]internal.GoCollectorRule, len(rules))
85+
for i, r := range rules {
86+
rs[i] = internal.GoCollectorRule{
87+
Matcher: r.Matcher,
88+
}
8989
}
90+
91+
return func(o *internal.GoCollectorOptions) {
92+
o.DisableMemStatsLikeMetrics = true
93+
}
94+
}
95+
96+
// WithoutGoCollectorRuntimeMetrics allows disabling group of runtime/metrics that you might have added in WithGoCollectorRuntimeMetrics.
97+
// It behaves similarly to WithGoCollectorRuntimeMetrics just with deny-list semantics.
98+
func WithoutGoCollectorRuntimeMetrics(matchers ...*regexp.Regexp) func(options *internal.GoCollectorOptions) {
99+
rs := make([]internal.GoCollectorRule, len(matchers))
100+
for i, m := range matchers {
101+
rs[i] = internal.GoCollectorRule{
102+
Matcher: m,
103+
Deny: true,
104+
}
105+
}
106+
107+
return func(o *internal.GoCollectorOptions) {
108+
o.RuntimeMetricRules = append(o.RuntimeMetricRules, rs...)
109+
}
110+
}
111+
112+
// NewGoCollector returns a collector that exports metrics about the current Go
113+
// process using debug.GCStats and runtime/metrics.
114+
func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) prometheus.Collector {
90115
//nolint:staticcheck // Ignore SA1019 until v2.
91-
return prometheus.NewGoCollector(promPkgOpts...)
116+
return prometheus.NewGoCollector(opts...)
92117
}

prometheus/collectors/go_collector_latest_test.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package collectors
1818

1919
import (
2020
"encoding/json"
21+
"regexp"
2122
"testing"
2223

2324
"github.com/prometheus/client_golang/prometheus"
@@ -26,7 +27,9 @@ import (
2627
func TestGoCollectorMarshalling(t *testing.T) {
2728
reg := prometheus.NewRegistry()
2829
reg.MustRegister(NewGoCollector(
29-
WithGoCollections(GoRuntimeMemStatsCollection | GoRuntimeMetricsCollection),
30+
WithGoCollectorRuntimeMetrics(GoRuntimeMetricsRule{
31+
Matcher: regexp.MustCompile("/.*"),
32+
}),
3033
))
3134
result, err := reg.Gather()
3235
if err != nil {
@@ -37,3 +40,9 @@ func TestGoCollectorMarshalling(t *testing.T) {
3740
t.Errorf("json marshalling shoud not fail, %v", err)
3841
}
3942
}
43+
44+
func ExampleGoCollector() {
45+
}
46+
47+
func ExampleGoCollector_WithAdvancedGoMetrics() {
48+
}

prometheus/go_collector.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ import (
1919
"time"
2020
)
2121

22+
// goRuntimeMemStats provides the metrics initially provided by runtime.ReadMemStats.
23+
// From Go 1.17 those similar (and better) statistics are provided by runtime/metrics, so
24+
// while eval closure works on runtime.MemStats, the struct from Go 1.17+ is
25+
// populated using runtime/metrics.
2226
func goRuntimeMemStats() memStatsMetrics {
2327
return memStatsMetrics{
2428
{
@@ -224,7 +228,7 @@ func newBaseGoCollector() baseGoCollector {
224228
"A summary of the pause duration of garbage collection cycles.",
225229
nil, nil),
226230
gcLastTimeDesc: NewDesc(
227-
memstatNamespace("last_gc_time_seconds"),
231+
"go_memstats_last_gc_time_seconds",
228232
"Number of seconds since 1970 of last garbage collection.",
229233
nil, nil),
230234
goInfoDesc: NewDesc(
@@ -269,7 +273,6 @@ func memstatNamespace(s string) string {
269273

270274
// memStatsMetrics provide description, evaluator, runtime/metrics name, and
271275
// value type for memstat metrics.
272-
// TODO(bwplotka): Remove with end Go 1.16 EOL and replace with runtime/metrics.Description
273276
type memStatsMetrics []struct {
274277
desc *Desc
275278
eval func(*runtime.MemStats) float64

0 commit comments

Comments
 (0)