mirror of
https://github.com/prometheus/prometheus.git
synced 2025-08-05 13:47:10 +02:00
config: address edge case where local config specifies validation mode only (#16923)
This check ensures that local ScrapeConfigs that only specify Legacy validation do not inherit the default global AllowUTF8 escaping setting, which is an invalid combination of settings. --------- Signed-off-by: Owen Williams <owen.williams@grafana.com>
This commit is contained in:
parent
5cc49720ac
commit
74610b7c89
@ -3,6 +3,7 @@
|
|||||||
## main / unreleased
|
## main / unreleased
|
||||||
|
|
||||||
* [BUGFIX] OTLP receiver: Generate `target_info` samples between the earliest and latest samples per resource. #16737
|
* [BUGFIX] OTLP receiver: Generate `target_info` samples between the earliest and latest samples per resource. #16737
|
||||||
|
* [BUGFIX] Config: Infer escaping scheme when scrape config validation scheme is set.
|
||||||
|
|
||||||
## 3.5.0 / 2025-07-14
|
## 3.5.0 / 2025-07-14
|
||||||
|
|
||||||
|
@ -885,8 +885,10 @@ func (c *ScrapeConfig) Validate(globalConfig GlobalConfig) error {
|
|||||||
return fmt.Errorf("unknown global name validation method specified, must be either '', 'legacy' or 'utf8', got %s", globalConfig.MetricNameValidationScheme)
|
return fmt.Errorf("unknown global name validation method specified, must be either '', 'legacy' or 'utf8', got %s", globalConfig.MetricNameValidationScheme)
|
||||||
}
|
}
|
||||||
// Scrapeconfig validation scheme matches global if left blank.
|
// Scrapeconfig validation scheme matches global if left blank.
|
||||||
|
localValidationUnset := false
|
||||||
switch c.MetricNameValidationScheme {
|
switch c.MetricNameValidationScheme {
|
||||||
case model.UnsetValidation:
|
case model.UnsetValidation:
|
||||||
|
localValidationUnset = true
|
||||||
c.MetricNameValidationScheme = globalConfig.MetricNameValidationScheme
|
c.MetricNameValidationScheme = globalConfig.MetricNameValidationScheme
|
||||||
case model.LegacyValidation, model.UTF8Validation:
|
case model.LegacyValidation, model.UTF8Validation:
|
||||||
default:
|
default:
|
||||||
@ -906,8 +908,20 @@ func (c *ScrapeConfig) Validate(globalConfig GlobalConfig) error {
|
|||||||
return fmt.Errorf("unknown global name escaping method specified, must be one of '%s', '%s', '%s', or '%s', got %q", model.AllowUTF8, model.EscapeUnderscores, model.EscapeDots, model.EscapeValues, globalConfig.MetricNameEscapingScheme)
|
return fmt.Errorf("unknown global name escaping method specified, must be one of '%s', '%s', '%s', or '%s', got %q", model.AllowUTF8, model.EscapeUnderscores, model.EscapeDots, model.EscapeValues, globalConfig.MetricNameEscapingScheme)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Similarly, if ScrapeConfig escaping scheme is blank, infer it from the
|
||||||
|
// ScrapeConfig validation scheme if that was set, or the Global validation
|
||||||
|
// scheme if the ScrapeConfig validation scheme was also not set. This ensures
|
||||||
|
// that local ScrapeConfigs that only specify Legacy validation do not inherit
|
||||||
|
// the global AllowUTF8 escaping setting, which is an error.
|
||||||
if c.MetricNameEscapingScheme == "" {
|
if c.MetricNameEscapingScheme == "" {
|
||||||
c.MetricNameEscapingScheme = globalConfig.MetricNameEscapingScheme
|
//nolint:gocritic
|
||||||
|
if localValidationUnset {
|
||||||
|
c.MetricNameEscapingScheme = globalConfig.MetricNameEscapingScheme
|
||||||
|
} else if c.MetricNameValidationScheme == model.LegacyValidation {
|
||||||
|
c.MetricNameEscapingScheme = model.EscapeUnderscores
|
||||||
|
} else {
|
||||||
|
c.MetricNameEscapingScheme = model.AllowUTF8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch c.MetricNameEscapingScheme {
|
switch c.MetricNameEscapingScheme {
|
||||||
|
@ -2801,29 +2801,40 @@ func TestScrapeConfigDisableCompression(t *testing.T) {
|
|||||||
|
|
||||||
func TestScrapeConfigNameValidationSettings(t *testing.T) {
|
func TestScrapeConfigNameValidationSettings(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
inputFile string
|
inputFile string
|
||||||
expectScheme model.ValidationScheme
|
expectScheme model.ValidationScheme
|
||||||
|
expectEscaping model.EscapingScheme
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "blank config implies default",
|
name: "blank config implies default",
|
||||||
inputFile: "scrape_config_default_validation_mode",
|
inputFile: "scrape_config_default_validation_mode",
|
||||||
expectScheme: model.UTF8Validation,
|
expectScheme: model.UTF8Validation,
|
||||||
|
expectEscaping: model.NoEscaping,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "global setting implies local settings",
|
name: "global setting implies local settings",
|
||||||
inputFile: "scrape_config_global_validation_mode",
|
inputFile: "scrape_config_global_validation_mode",
|
||||||
expectScheme: model.LegacyValidation,
|
expectScheme: model.LegacyValidation,
|
||||||
|
expectEscaping: model.DotsEscaping,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "local setting",
|
name: "local setting",
|
||||||
inputFile: "scrape_config_local_validation_mode",
|
inputFile: "scrape_config_local_validation_mode",
|
||||||
expectScheme: model.LegacyValidation,
|
expectScheme: model.LegacyValidation,
|
||||||
|
expectEscaping: model.ValueEncodingEscaping,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "local setting overrides global setting",
|
name: "local setting overrides global setting",
|
||||||
inputFile: "scrape_config_local_global_validation_mode",
|
inputFile: "scrape_config_local_global_validation_mode",
|
||||||
expectScheme: model.UTF8Validation,
|
expectScheme: model.UTF8Validation,
|
||||||
|
expectEscaping: model.DotsEscaping,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "local validation implies underscores escaping",
|
||||||
|
inputFile: "scrape_config_local_infer_escaping",
|
||||||
|
expectScheme: model.LegacyValidation,
|
||||||
|
expectEscaping: model.UnderscoreEscaping,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2839,6 +2850,10 @@ func TestScrapeConfigNameValidationSettings(t *testing.T) {
|
|||||||
require.NoError(t, yaml.UnmarshalStrict(out, got))
|
require.NoError(t, yaml.UnmarshalStrict(out, got))
|
||||||
|
|
||||||
require.Equal(t, tc.expectScheme, got.ScrapeConfigs[0].MetricNameValidationScheme)
|
require.Equal(t, tc.expectScheme, got.ScrapeConfigs[0].MetricNameValidationScheme)
|
||||||
|
|
||||||
|
escaping, err := model.ToEscapingScheme(got.ScrapeConfigs[0].MetricNameEscapingScheme)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, tc.expectEscaping, escaping)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
3
config/testdata/scrape_config_local_infer_escaping.yml
vendored
Normal file
3
config/testdata/scrape_config_local_infer_escaping.yml
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
scrape_configs:
|
||||||
|
- job_name: prometheus
|
||||||
|
metric_name_validation_scheme: legacy
|
Loading…
Reference in New Issue
Block a user