fix(config): respect GOGC environment variable if no "runtime" block exists

Fixes: https://github.com/prometheus/prometheus/issues/16334
Related to:
- https://github.com/prometheus/prometheus/pull/15238
- https://github.com/prometheus/prometheus/pull/16052

Currently, when the GOGC environment variable is set -- and no `runtime`
block is set in the Prometheus config file -- it is ignored and the
default value of 75% is always used.

However, if there is an empty runtime block (e.g. `runtime: {}`), _then_
the GOGC environment variable is checked.

This PR changes this behavior to consistently check and use the GOGC
environment variable when it is set (unless the `gogc` field is set in
the `runtime` block of the loaded config file, in which case it still
gives that precedence).

Co-authored-by: Adam Rambo <arambo@protonmail.com>
Signed-off-by: Will Hegedus <whegedus@akamai.com>
This commit is contained in:
Will Hegedus 2025-05-05 16:53:58 -04:00
parent dbf5d01a62
commit 33578fedb3

View File

@ -175,7 +175,7 @@ var (
DefaultRuntimeConfig = RuntimeConfig{ DefaultRuntimeConfig = RuntimeConfig{
// Go runtime tuning. // Go runtime tuning.
GoGC: 75, GoGC: getGoGC(),
} }
// DefaultScrapeConfig is the default scrape configuration. // DefaultScrapeConfig is the default scrape configuration.
@ -385,8 +385,6 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error {
// We have to restore it here. // We have to restore it here.
if c.Runtime.isZero() { if c.Runtime.isZero() {
c.Runtime = DefaultRuntimeConfig c.Runtime = DefaultRuntimeConfig
// Use the GOGC env var value if the runtime section is empty.
c.Runtime.GoGC = getGoGCEnv()
} }
for _, rf := range c.RuleFiles { for _, rf := range c.RuleFiles {
@ -652,6 +650,8 @@ func (c *GlobalConfig) isZero() bool {
!c.AlwaysScrapeClassicHistograms !c.AlwaysScrapeClassicHistograms
} }
const DefaultGoGCPercentage = 75
// RuntimeConfig configures the values for the process behavior. // RuntimeConfig configures the values for the process behavior.
type RuntimeConfig struct { type RuntimeConfig struct {
// The Go garbage collection target percentage. // The Go garbage collection target percentage.
@ -1494,7 +1494,7 @@ func fileErr(filename string, err error) error {
return fmt.Errorf("%q: %w", filePath(filename), err) return fmt.Errorf("%q: %w", filePath(filename), err)
} }
func getGoGCEnv() int { func getGoGC() int {
goGCEnv := os.Getenv("GOGC") goGCEnv := os.Getenv("GOGC")
// If the GOGC env var is set, use the same logic as upstream Go. // If the GOGC env var is set, use the same logic as upstream Go.
if goGCEnv != "" { if goGCEnv != "" {
@ -1507,7 +1507,7 @@ func getGoGCEnv() int {
return i return i
} }
} }
return DefaultRuntimeConfig.GoGC return DefaultGoGCPercentage
} }
type translationStrategyOption string type translationStrategyOption string