Do not panic on unsupported Go runtime metrics

Log the unsupported Go runtime metrics on startup instead, so the user is aware of unsupported metrics.
The solution for removing the log lines is to upgrade Go builder.

Reduce the minimum supported Go version at go.mod from Go1.20 to Go1.16, where the runtime/metrics package has been added.
See https://tip.golang.org/doc/go1.16#runtime

Updates https://github.com/VictoriaMetrics/metrics/issues/59
Updates https://github.com/VictoriaMetrics/metrics/pull/60
This commit is contained in:
Aliaksandr Valialkin 2023-12-17 16:25:33 +02:00
parent cd448dd4c1
commit 447d235cbb
No known key found for this signature in database
GPG Key ID: 52C003EE2BCDB9EB
7 changed files with 47 additions and 10 deletions

4
go.mod
View File

@ -5,6 +5,4 @@ require (
golang.org/x/sys v0.15.0 golang.org/x/sys v0.15.0
) )
require github.com/valyala/fastrand v1.1.0 // indirect go 1.16
go 1.20

View File

@ -3,6 +3,7 @@ package metrics
import ( import (
"fmt" "fmt"
"io" "io"
"log"
"math" "math"
"runtime" "runtime"
runtimemetrics "runtime/metrics" runtimemetrics "runtime/metrics"
@ -22,6 +23,25 @@ var runtimeMetrics = [][2]string{
{"/gc/gomemlimit:bytes", "go_memlimit_bytes"}, {"/gc/gomemlimit:bytes", "go_memlimit_bytes"},
} }
var supportedRuntimeMetrics = initSupportedRuntimeMetrics(runtimeMetrics)
func initSupportedRuntimeMetrics(rms [][2]string) [][2]string {
exposedMetrics := make(map[string]struct{})
for _, d := range runtimemetrics.All() {
exposedMetrics[d.Name] = struct{}{}
}
var supportedMetrics [][2]string
for _, rm := range rms {
metricName := rm[0]
if _, ok := exposedMetrics[metricName]; ok {
supportedMetrics = append(supportedMetrics, rm)
} else {
log.Printf("github.com/VictoriaMetrics/metrics: do not expose %s metric, since the corresponding metric %s isn't supported in the current Go runtime", rm[1], metricName)
}
}
return supportedMetrics
}
func writeGoMetrics(w io.Writer) { func writeGoMetrics(w io.Writer) {
writeRuntimeMetrics(w) writeRuntimeMetrics(w)
@ -81,18 +101,19 @@ func writeGoMetrics(w io.Writer) {
} }
func writeRuntimeMetrics(w io.Writer) { func writeRuntimeMetrics(w io.Writer) {
samples := make([]runtimemetrics.Sample, len(runtimeMetrics)) samples := make([]runtimemetrics.Sample, len(supportedRuntimeMetrics))
for i, rm := range runtimeMetrics { for i, rm := range supportedRuntimeMetrics {
samples[i].Name = rm[0] samples[i].Name = rm[0]
} }
runtimemetrics.Read(samples) runtimemetrics.Read(samples)
for i, rm := range runtimeMetrics { for i, rm := range supportedRuntimeMetrics {
writeRuntimeMetric(w, rm[1], &samples[i]) writeRuntimeMetric(w, rm[1], &samples[i])
} }
} }
func writeRuntimeMetric(w io.Writer, name string, sample *runtimemetrics.Sample) { func writeRuntimeMetric(w io.Writer, name string, sample *runtimemetrics.Sample) {
switch sample.Value.Kind() { kind := sample.Value.Kind()
switch kind {
case runtimemetrics.KindBad: case runtimemetrics.KindBad:
panic(fmt.Errorf("BUG: unexpected runtimemetrics.KindBad for sample.Name=%q", sample.Name)) panic(fmt.Errorf("BUG: unexpected runtimemetrics.KindBad for sample.Name=%q", sample.Name))
case runtimemetrics.KindUint64: case runtimemetrics.KindUint64:
@ -101,6 +122,8 @@ func writeRuntimeMetric(w io.Writer, name string, sample *runtimemetrics.Sample)
fmt.Fprintf(w, "%s %g\n", name, sample.Value.Float64()) fmt.Fprintf(w, "%s %g\n", name, sample.Value.Float64())
case runtimemetrics.KindFloat64Histogram: case runtimemetrics.KindFloat64Histogram:
writeRuntimeHistogramMetric(w, name, sample.Value.Float64Histogram()) writeRuntimeHistogramMetric(w, name, sample.Value.Float64Histogram())
default:
panic(fmt.Errorf("unexpected metric kind=%d", kind))
} }
} }

View File

@ -1,12 +1,21 @@
package metrics package metrics
import ( import (
"bytes"
"math" "math"
runtimemetrics "runtime/metrics" runtimemetrics "runtime/metrics"
"strings" "strings"
"testing" "testing"
) )
func TestWriteRuntimeMetrics(t *testing.T) {
var bb bytes.Buffer
writeRuntimeMetrics(&bb)
if n := bb.Len(); n == 0 {
t.Fatalf("unexpected empty runtime metrics")
}
}
func TestWriteRuntimeHistogramMetricOk(t *testing.T) { func TestWriteRuntimeHistogramMetricOk(t *testing.T) {
f := func(h *runtimemetrics.Float64Histogram, resultExpected string) { f := func(h *runtimemetrics.Float64Histogram, resultExpected string) {
t.Helper() t.Helper()

1
vendor/github.com/valyala/fastrand/go.mod generated vendored Normal file
View File

@ -0,0 +1 @@
module github.com/valyala/fastrand

5
vendor/github.com/valyala/histogram/go.mod generated vendored Normal file
View File

@ -0,0 +1,5 @@
module github.com/valyala/histogram
go 1.12
require github.com/valyala/fastrand v1.1.0

2
vendor/github.com/valyala/histogram/go.sum generated vendored Normal file
View File

@ -0,0 +1,2 @@
github.com/valyala/fastrand v1.1.0 h1:f+5HkLW4rsgzdNoleUOB69hyT9IlD2ZQh9GyDMfb5G8=
github.com/valyala/fastrand v1.1.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ=

5
vendor/modules.txt vendored
View File

@ -1,9 +1,8 @@
# github.com/valyala/fastrand v1.1.0 # github.com/valyala/fastrand v1.1.0
## explicit
github.com/valyala/fastrand github.com/valyala/fastrand
# github.com/valyala/histogram v1.2.0 # github.com/valyala/histogram v1.2.0
## explicit; go 1.12 ## explicit
github.com/valyala/histogram github.com/valyala/histogram
# golang.org/x/sys v0.15.0 # golang.org/x/sys v0.15.0
## explicit; go 1.18 ## explicit
golang.org/x/sys/windows golang.org/x/sys/windows