Skip to content

Commit 6566c5a

Browse files
authored
scrape: Add config option for escaping scheme request. (prometheus#16066)
The new metric_name_escaping_scheme config option works in parallel with metric_name_validation_scheme and controls which escaping scheme is requested when scraping. When not specified, the scheme will request underscores if the validation scheme is set to legacy, and will request allow-utf-8 when the validation scheme is set to utf8. This setting allows users to allow utf8 names if they like, but explicitly request an escaping scheme rather than UTF-8. Fixes prometheus#16034 Built on prometheus#16080 Signed-off-by: Owen Williams <owen.williams@grafana.com>
1 parent de399eb commit 6566c5a

9 files changed

+900
-558
lines changed

config/config.go

+64-5
Original file line numberDiff line numberDiff line change
@@ -479,8 +479,13 @@ type GlobalConfig struct {
479479
// Keep no more than this many dropped targets per job.
480480
// 0 means no limit.
481481
KeepDroppedTargets uint `yaml:"keep_dropped_targets,omitempty"`
482-
// Allow UTF8 Metric and Label Names.
482+
// Allow UTF8 Metric and Label Names. Can be blank in config files but must
483+
// have a value if a ScrepeConfig is created programmatically.
483484
MetricNameValidationScheme string `yaml:"metric_name_validation_scheme,omitempty"`
485+
// Metric name escaping mode to request through content negotiation. Can be
486+
// blank in config files but must have a value if a ScrepeConfig is created
487+
// programmatically.
488+
MetricNameEscapingScheme string `yaml:"metric_name_escaping_scheme,omitempty"`
484489
}
485490

486491
// ScrapeProtocol represents supported protocol for scraping metrics.
@@ -719,8 +724,13 @@ type ScrapeConfig struct {
719724
// Keep no more than this many dropped targets per job.
720725
// 0 means no limit.
721726
KeepDroppedTargets uint `yaml:"keep_dropped_targets,omitempty"`
722-
// Allow UTF8 Metric and Label Names.
727+
// Allow UTF8 Metric and Label Names. Can be blank in config files but must
728+
// have a value if a ScrepeConfig is created programmatically.
723729
MetricNameValidationScheme string `yaml:"metric_name_validation_scheme,omitempty"`
730+
// Metric name escaping mode to request through content negotiation. Can be
731+
// blank in config files but must have a value if a ScrepeConfig is created
732+
// programmatically.
733+
MetricNameEscapingScheme string `yaml:"metric_name_escaping_scheme,omitempty"`
724734

725735
// We cannot do proper Go type embedding below as the parser will then parse
726736
// values arbitrarily into the overflow maps of further-down types.
@@ -841,13 +851,48 @@ func (c *ScrapeConfig) Validate(globalConfig GlobalConfig) error {
841851
if model.NameValidationScheme != model.UTF8Validation {
842852
return errors.New("model.NameValidationScheme must be set to UTF8")
843853
}
854+
844855
switch globalConfig.MetricNameValidationScheme {
845-
case "", LegacyValidationConfig, UTF8ValidationConfig:
856+
case "":
857+
globalConfig.MetricNameValidationScheme = UTF8ValidationConfig
858+
case LegacyValidationConfig, UTF8ValidationConfig:
846859
default:
847-
return fmt.Errorf("unknown name validation method specified, must be either 'legacy' or 'utf8', got %s", globalConfig.MetricNameValidationScheme)
860+
return fmt.Errorf("unknown global name validation method specified, must be either 'legacy' or 'utf8', got %s", globalConfig.MetricNameValidationScheme)
848861
}
849-
if c.MetricNameValidationScheme == "" {
862+
// Scrapeconfig validation scheme matches global if left blank.
863+
switch c.MetricNameValidationScheme {
864+
case "":
850865
c.MetricNameValidationScheme = globalConfig.MetricNameValidationScheme
866+
case LegacyValidationConfig, UTF8ValidationConfig:
867+
default:
868+
return fmt.Errorf("unknown scrape config name validation method specified, must be either 'legacy' or 'utf8', got %s", c.MetricNameValidationScheme)
869+
}
870+
871+
// Escaping scheme is based on the validation scheme if left blank.
872+
switch globalConfig.MetricNameEscapingScheme {
873+
case "":
874+
if globalConfig.MetricNameValidationScheme == LegacyValidationConfig {
875+
globalConfig.MetricNameEscapingScheme = model.EscapeUnderscores
876+
} else {
877+
globalConfig.MetricNameEscapingScheme = model.AllowUTF8
878+
}
879+
case model.AllowUTF8, model.EscapeUnderscores, model.EscapeDots, model.EscapeValues:
880+
default:
881+
return fmt.Errorf("unknown global name escaping method specified, must be one of '%s', '%s', '%s', or '%s', got %s", model.AllowUTF8, model.EscapeUnderscores, model.EscapeDots, model.EscapeValues, globalConfig.MetricNameValidationScheme)
882+
}
883+
884+
if c.MetricNameEscapingScheme == "" {
885+
c.MetricNameEscapingScheme = globalConfig.MetricNameEscapingScheme
886+
}
887+
888+
switch c.MetricNameEscapingScheme {
889+
case model.AllowUTF8:
890+
if c.MetricNameValidationScheme != UTF8ValidationConfig {
891+
return errors.New("utf8 metric names requested but validation scheme is not set to UTF8")
892+
}
893+
case model.EscapeUnderscores, model.EscapeDots, model.EscapeValues:
894+
default:
895+
return fmt.Errorf("unknown scrape config name escaping method specified, must be one of '%s', '%s', '%s', or '%s', got %s", model.AllowUTF8, model.EscapeUnderscores, model.EscapeDots, model.EscapeValues, c.MetricNameValidationScheme)
851896
}
852897

853898
return nil
@@ -858,6 +903,20 @@ func (c *ScrapeConfig) MarshalYAML() (interface{}, error) {
858903
return discovery.MarshalYAMLWithInlineConfigs(c)
859904
}
860905

906+
// ToValidationScheme returns the validation scheme for the given string config value.
907+
func ToValidationScheme(s string) (validationScheme model.ValidationScheme, err error) {
908+
switch s {
909+
case UTF8ValidationConfig:
910+
validationScheme = model.UTF8Validation
911+
case LegacyValidationConfig:
912+
validationScheme = model.LegacyValidation
913+
default:
914+
return model.UTF8Validation, fmt.Errorf("invalid metric name validation scheme, %s", s)
915+
}
916+
917+
return validationScheme, nil
918+
}
919+
861920
// StorageConfig configures runtime reloadable configuration options.
862921
type StorageConfig struct {
863922
TSDBConfig *TSDBConfig `yaml:"tsdb,omitempty"`

0 commit comments

Comments
 (0)