Phase out native histogram feature flag

The detailed plan for this is laid out in
https://github.com/prometheus/prometheus/issues/16572 .

This commit adds a global and local scrape config option
`scrape_native_histograms`, which has to be set to true to ingest
native histograms.

To ease the transition, the feature flag is changed to simply set the
default of `scrape_native_histograms` to true.

Further implications:

- The default scrape protocols now depend on the
  `scrape_native_histograms` setting.
- Everywhere else, histograms are now "on by default".

Documentation beyond the one for the feature flag and the scrape
config are deliberately left out. See
https://github.com/prometheus/prometheus/pull/17232 for that.

Signed-off-by: beorn7 <beorn@grafana.com>
This commit is contained in:
beorn7 2025-10-09 16:56:13 +02:00
parent 72960c076d
commit ad7d1aed99
33 changed files with 1857 additions and 339 deletions

View File

@ -254,12 +254,11 @@ func (c *flagConfig) setFeatureListOptions(logger *slog.Logger) error {
parser.ExperimentalDurationExpr = true parser.ExperimentalDurationExpr = true
logger.Info("Experimental duration expression parsing enabled.") logger.Info("Experimental duration expression parsing enabled.")
case "native-histograms": case "native-histograms":
c.tsdb.EnableNativeHistograms = true
c.scrape.EnableNativeHistogramsIngestion = true
// Change relevant global variables. Hacky, but it's hard to pass a new option or default to unmarshallers. // Change relevant global variables. Hacky, but it's hard to pass a new option or default to unmarshallers.
config.DefaultConfig.GlobalConfig.ScrapeProtocols = config.DefaultProtoFirstScrapeProtocols t := true
config.DefaultGlobalConfig.ScrapeProtocols = config.DefaultProtoFirstScrapeProtocols config.DefaultConfig.GlobalConfig.ScrapeNativeHistograms = &t
logger.Info("Experimental native histogram support enabled. Changed default scrape_protocols to prefer PrometheusProto format.", "global.scrape_protocols", fmt.Sprintf("%v", config.DefaultGlobalConfig.ScrapeProtocols)) config.DefaultGlobalConfig.ScrapeNativeHistograms = &t
logger.Warn("This option for --enable-feature is being phased out. It currently changes the default for the scrape_native_histograms scrape config setting to true, but will become a no-op in v3.9+. Stop using this option and set scrape_native_histograms in the scrape config instead.", "option", o)
case "ooo-native-histograms": case "ooo-native-histograms":
logger.Warn("This option for --enable-feature is now permanently enabled and therefore a no-op.", "option", o) logger.Warn("This option for --enable-feature is now permanently enabled and therefore a no-op.", "option", o)
case "created-timestamp-zero-ingestion": case "created-timestamp-zero-ingestion":
@ -1875,7 +1874,6 @@ type tsdbOptions struct {
EnableExemplarStorage bool EnableExemplarStorage bool
MaxExemplars int64 MaxExemplars int64
EnableMemorySnapshotOnShutdown bool EnableMemorySnapshotOnShutdown bool
EnableNativeHistograms bool
EnableDelayedCompaction bool EnableDelayedCompaction bool
CompactionDelayMaxPercent int CompactionDelayMaxPercent int
EnableOverlappingCompaction bool EnableOverlappingCompaction bool
@ -1898,7 +1896,6 @@ func (opts tsdbOptions) ToTSDBOptions() tsdb.Options {
EnableExemplarStorage: opts.EnableExemplarStorage, EnableExemplarStorage: opts.EnableExemplarStorage,
MaxExemplars: opts.MaxExemplars, MaxExemplars: opts.MaxExemplars,
EnableMemorySnapshotOnShutdown: opts.EnableMemorySnapshotOnShutdown, EnableMemorySnapshotOnShutdown: opts.EnableMemorySnapshotOnShutdown,
EnableNativeHistograms: opts.EnableNativeHistograms,
OutOfOrderTimeWindow: opts.OutOfOrderTimeWindow, OutOfOrderTimeWindow: opts.OutOfOrderTimeWindow,
EnableDelayedCompaction: opts.EnableDelayedCompaction, EnableDelayedCompaction: opts.EnableDelayedCompaction,
CompactionDelayMaxPercent: opts.CompactionDelayMaxPercent, CompactionDelayMaxPercent: opts.CompactionDelayMaxPercent,

View File

@ -157,15 +157,22 @@ var (
OTLPConfig: DefaultOTLPConfig, OTLPConfig: DefaultOTLPConfig,
} }
f bool
// DefaultGlobalConfig is the default global configuration. // DefaultGlobalConfig is the default global configuration.
DefaultGlobalConfig = GlobalConfig{ DefaultGlobalConfig = GlobalConfig{
ScrapeInterval: model.Duration(1 * time.Minute), ScrapeInterval: model.Duration(1 * time.Minute),
ScrapeTimeout: model.Duration(10 * time.Second), ScrapeTimeout: model.Duration(10 * time.Second),
EvaluationInterval: model.Duration(1 * time.Minute), EvaluationInterval: model.Duration(1 * time.Minute),
RuleQueryOffset: model.Duration(0 * time.Minute), RuleQueryOffset: model.Duration(0 * time.Minute),
// When native histogram feature flag is enabled, ScrapeProtocols default // This is nil to be able to distinguish between the case when
// changes to DefaultNativeHistogramScrapeProtocols. // the normal default should be used and the case when a
ScrapeProtocols: DefaultScrapeProtocols, // new default is needed due to an enabled feature flag.
// E.g. set to `DefaultProtoFirstScrapeProtocols` when
// the feature flag `created-timestamp-zero-ingestion` is set.
ScrapeProtocols: nil,
// When the native histogram feature flag is enabled,
// ScrapeNativeHistograms default changes to true.
ScrapeNativeHistograms: &f,
ConvertClassicHistogramsToNHCB: false, ConvertClassicHistogramsToNHCB: false,
AlwaysScrapeClassicHistograms: false, AlwaysScrapeClassicHistograms: false,
MetricNameValidationScheme: model.UTF8Validation, MetricNameValidationScheme: model.UTF8Validation,
@ -455,7 +462,7 @@ type GlobalConfig struct {
// The protocols to negotiate during a scrape. It tells clients what // The protocols to negotiate during a scrape. It tells clients what
// protocol are accepted by Prometheus and with what weight (most wanted is first). // protocol are accepted by Prometheus and with what weight (most wanted is first).
// Supported values (case sensitive): PrometheusProto, OpenMetricsText0.0.1, // Supported values (case sensitive): PrometheusProto, OpenMetricsText0.0.1,
// OpenMetricsText1.0.0, PrometheusText0.0.4. // OpenMetricsText1.0.0, PrometheusText1.0.0, PrometheusText0.0.4
ScrapeProtocols []ScrapeProtocol `yaml:"scrape_protocols,omitempty"` ScrapeProtocols []ScrapeProtocol `yaml:"scrape_protocols,omitempty"`
// How frequently to evaluate rules by default. // How frequently to evaluate rules by default.
EvaluationInterval model.Duration `yaml:"evaluation_interval,omitempty"` EvaluationInterval model.Duration `yaml:"evaluation_interval,omitempty"`
@ -495,6 +502,8 @@ type GlobalConfig struct {
// blank in config files but must have a value if a ScrapeConfig is created // blank in config files but must have a value if a ScrapeConfig is created
// programmatically. // programmatically.
MetricNameEscapingScheme string `yaml:"metric_name_escaping_scheme,omitempty"` MetricNameEscapingScheme string `yaml:"metric_name_escaping_scheme,omitempty"`
// Whether to scrape native histograms.
ScrapeNativeHistograms *bool `yaml:"scrape_native_histograms,omitempty"`
// Whether to convert all scraped classic histograms into native histograms with custom buckets. // Whether to convert all scraped classic histograms into native histograms with custom buckets.
ConvertClassicHistogramsToNHCB bool `yaml:"convert_classic_histograms_to_nhcb,omitempty"` ConvertClassicHistogramsToNHCB bool `yaml:"convert_classic_histograms_to_nhcb,omitempty"`
// Whether to scrape a classic histogram, even if it is also exposed as a native histogram. // Whether to scrape a classic histogram, even if it is also exposed as a native histogram.
@ -635,12 +644,26 @@ func (c *GlobalConfig) UnmarshalYAML(unmarshal func(any) error) error {
if gc.EvaluationInterval == 0 { if gc.EvaluationInterval == 0 {
gc.EvaluationInterval = DefaultGlobalConfig.EvaluationInterval gc.EvaluationInterval = DefaultGlobalConfig.EvaluationInterval
} }
if gc.ScrapeNativeHistograms == nil {
if gc.ScrapeProtocols == nil { gc.ScrapeNativeHistograms = DefaultGlobalConfig.ScrapeNativeHistograms
gc.ScrapeProtocols = DefaultGlobalConfig.ScrapeProtocols
} }
if err := validateAcceptScrapeProtocols(gc.ScrapeProtocols); err != nil { if gc.ScrapeProtocols == nil {
return fmt.Errorf("%w for global config", err) if DefaultGlobalConfig.ScrapeProtocols != nil {
// This is the case where the defaults are set due to a feature flag.
// E.g. if the created-timestamp-zero-ingestion feature flag is
// used.
gc.ScrapeProtocols = DefaultGlobalConfig.ScrapeProtocols
}
// Otherwise, we leave ScrapeProtocols at nil for now. In the
// per-job scrape config, we have to recognize the unset case to
// correctly set the default depending on the local value of
// ScrapeNativeHistograms.
}
if gc.ScrapeProtocols != nil {
// Only validate if not-nil at this point.
if err := validateAcceptScrapeProtocols(gc.ScrapeProtocols); err != nil {
return fmt.Errorf("%w for global config", err)
}
} }
*c = *gc *c = *gc
@ -657,6 +680,7 @@ func (c *GlobalConfig) isZero() bool {
c.QueryLogFile == "" && c.QueryLogFile == "" &&
c.ScrapeFailureLogFile == "" && c.ScrapeFailureLogFile == "" &&
c.ScrapeProtocols == nil && c.ScrapeProtocols == nil &&
c.ScrapeNativeHistograms == nil &&
!c.ConvertClassicHistogramsToNHCB && !c.ConvertClassicHistogramsToNHCB &&
!c.AlwaysScrapeClassicHistograms !c.AlwaysScrapeClassicHistograms
} }
@ -719,6 +743,8 @@ type ScrapeConfig struct {
// Supported values (case sensitive): PrometheusProto, OpenMetricsText0.0.1, // Supported values (case sensitive): PrometheusProto, OpenMetricsText0.0.1,
// OpenMetricsText1.0.0, PrometheusText1.0.0, PrometheusText0.0.4. // OpenMetricsText1.0.0, PrometheusText1.0.0, PrometheusText0.0.4.
ScrapeFallbackProtocol ScrapeProtocol `yaml:"fallback_scrape_protocol,omitempty"` ScrapeFallbackProtocol ScrapeProtocol `yaml:"fallback_scrape_protocol,omitempty"`
// Whether to scrape native histograms.
ScrapeNativeHistograms *bool `yaml:"scrape_native_histograms,omitempty"`
// Whether to scrape a classic histogram, even if it is also exposed as a native histogram. // Whether to scrape a classic histogram, even if it is also exposed as a native histogram.
AlwaysScrapeClassicHistograms *bool `yaml:"always_scrape_classic_histograms,omitempty"` AlwaysScrapeClassicHistograms *bool `yaml:"always_scrape_classic_histograms,omitempty"`
// Whether to convert all scraped classic histograms into a native histogram with custom buckets. // Whether to convert all scraped classic histograms into a native histogram with custom buckets.
@ -863,9 +889,23 @@ func (c *ScrapeConfig) Validate(globalConfig GlobalConfig) error {
if c.ScrapeFailureLogFile == "" { if c.ScrapeFailureLogFile == "" {
c.ScrapeFailureLogFile = globalConfig.ScrapeFailureLogFile c.ScrapeFailureLogFile = globalConfig.ScrapeFailureLogFile
} }
if c.ScrapeNativeHistograms == nil {
c.ScrapeNativeHistograms = globalConfig.ScrapeNativeHistograms
}
if c.ScrapeProtocols == nil { if c.ScrapeProtocols == nil {
c.ScrapeProtocols = globalConfig.ScrapeProtocols switch {
case globalConfig.ScrapeProtocols != nil:
// global ScrapeProtocols either set explicitly or via a
// default triggered by a feature flag. This overrides
// the selection based on locally active scraping of
// native histograms.
c.ScrapeProtocols = globalConfig.ScrapeProtocols
case c.ScrapeNativeHistogramsEnabled():
c.ScrapeProtocols = DefaultProtoFirstScrapeProtocols
default:
c.ScrapeProtocols = DefaultScrapeProtocols
}
} }
if err := validateAcceptScrapeProtocols(c.ScrapeProtocols); err != nil { if err := validateAcceptScrapeProtocols(c.ScrapeProtocols); err != nil {
return fmt.Errorf("%w for scrape config with job name %q", err, c.JobName) return fmt.Errorf("%w for scrape config with job name %q", err, c.JobName)
@ -985,6 +1025,11 @@ func ToEscapingScheme(s string, v model.ValidationScheme) (model.EscapingScheme,
return model.ToEscapingScheme(s) return model.ToEscapingScheme(s)
} }
// ScrapeNativeHistogramsEnabled returns whether to scrape native histograms.
func (c *ScrapeConfig) ScrapeNativeHistogramsEnabled() bool {
return c.ScrapeNativeHistograms != nil && *c.ScrapeNativeHistograms
}
// ConvertClassicHistogramsToNHCBEnabled returns whether to convert classic histograms to NHCB. // ConvertClassicHistogramsToNHCBEnabled returns whether to convert classic histograms to NHCB.
func (c *ScrapeConfig) ConvertClassicHistogramsToNHCBEnabled() bool { func (c *ScrapeConfig) ConvertClassicHistogramsToNHCBEnabled() bool {
return c.ConvertClassicHistogramsToNHCB != nil && *c.ConvertClassicHistogramsToNHCB return c.ConvertClassicHistogramsToNHCB != nil && *c.ConvertClassicHistogramsToNHCB

View File

@ -105,7 +105,7 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: false, AlwaysScrapeClassicHistograms: false,
ConvertClassicHistogramsToNHCB: false, ConvertClassicHistogramsToNHCB: false,
MetricNameValidationScheme: model.UTF8Validation, MetricNameValidationScheme: model.UTF8Validation,
@ -225,11 +225,12 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFallbackProtocol: PrometheusText0_0_4, ScrapeFallbackProtocol: PrometheusText0_0_4,
ScrapeFailureLogFile: "testdata/fail_prom.log", ScrapeFailureLogFile: "testdata/fail_prom.log",
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -353,6 +354,7 @@ var expectedConf = &Config{
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -458,10 +460,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -519,10 +522,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -557,10 +561,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -601,10 +606,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -645,10 +651,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -679,10 +686,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -721,10 +729,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -760,10 +769,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -806,10 +816,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -842,10 +853,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -881,10 +893,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -913,10 +926,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -948,10 +962,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -983,10 +998,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -1018,10 +1034,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -1050,10 +1067,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -1090,10 +1108,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -1129,10 +1148,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -1165,10 +1185,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -1200,10 +1221,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -1239,10 +1261,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -1281,10 +1304,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultProtoFirstScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(true),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -1343,10 +1367,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -1375,10 +1400,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -1418,10 +1444,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -1467,10 +1494,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -1506,10 +1534,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -1546,10 +1575,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -1581,10 +1611,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -1618,10 +1649,11 @@ var expectedConf = &Config{
LabelLimit: globLabelLimit, LabelLimit: globLabelLimit,
LabelNameLengthLimit: globLabelNameLengthLimit, LabelNameLengthLimit: globLabelNameLengthLimit,
LabelValueLengthLimit: globLabelValueLengthLimit, LabelValueLengthLimit: globLabelValueLengthLimit,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
ScrapeFailureLogFile: globScrapeFailureLogFile, ScrapeFailureLogFile: globScrapeFailureLogFile,
MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme, MetricNameValidationScheme: DefaultGlobalConfig.MetricNameValidationScheme,
MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme, MetricNameEscapingScheme: DefaultGlobalConfig.MetricNameEscapingScheme,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -2595,6 +2627,8 @@ type ScrapeConfigOptions struct {
JobName string JobName string
ScrapeInterval model.Duration ScrapeInterval model.Duration
ScrapeTimeout model.Duration ScrapeTimeout model.Duration
ScrapeProtocols []ScrapeProtocol // Set to DefaultScrapeProtocols by default.
ScrapeNativeHistograms bool
AlwaysScrapeClassicHistograms bool AlwaysScrapeClassicHistograms bool
ConvertClassicHistToNHCB bool ConvertClassicHistToNHCB bool
} }
@ -2602,12 +2636,12 @@ type ScrapeConfigOptions struct {
func TestGetScrapeConfigs(t *testing.T) { func TestGetScrapeConfigs(t *testing.T) {
// Helper function to create a scrape config with the given options. // Helper function to create a scrape config with the given options.
sc := func(opts ScrapeConfigOptions) *ScrapeConfig { sc := func(opts ScrapeConfigOptions) *ScrapeConfig {
return &ScrapeConfig{ sc := ScrapeConfig{
JobName: opts.JobName, JobName: opts.JobName,
HonorTimestamps: true, HonorTimestamps: true,
ScrapeInterval: opts.ScrapeInterval, ScrapeInterval: opts.ScrapeInterval,
ScrapeTimeout: opts.ScrapeTimeout, ScrapeTimeout: opts.ScrapeTimeout,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: opts.ScrapeProtocols,
MetricNameValidationScheme: model.UTF8Validation, MetricNameValidationScheme: model.UTF8Validation,
MetricNameEscapingScheme: model.AllowUTF8, MetricNameEscapingScheme: model.AllowUTF8,
@ -2627,9 +2661,14 @@ func TestGetScrapeConfigs(t *testing.T) {
}, },
}, },
}, },
ScrapeNativeHistograms: boolPtr(opts.ScrapeNativeHistograms),
AlwaysScrapeClassicHistograms: boolPtr(opts.AlwaysScrapeClassicHistograms), AlwaysScrapeClassicHistograms: boolPtr(opts.AlwaysScrapeClassicHistograms),
ConvertClassicHistogramsToNHCB: boolPtr(opts.ConvertClassicHistToNHCB), ConvertClassicHistogramsToNHCB: boolPtr(opts.ConvertClassicHistToNHCB),
} }
if opts.ScrapeProtocols == nil {
sc.ScrapeProtocols = DefaultScrapeProtocols
}
return &sc
} }
testCases := []struct { testCases := []struct {
@ -2639,22 +2678,57 @@ func TestGetScrapeConfigs(t *testing.T) {
expectedError string expectedError string
}{ }{
{ {
name: "An included config file should be a valid global config.", name: "An included config file should be a valid global config.",
configFile: "testdata/scrape_config_files.good.yml", configFile: "testdata/scrape_config_files.good.yml",
expectedResult: []*ScrapeConfig{sc(ScrapeConfigOptions{JobName: "prometheus", ScrapeInterval: model.Duration(60 * time.Second), ScrapeTimeout: model.Duration(10 * time.Second), AlwaysScrapeClassicHistograms: false, ConvertClassicHistToNHCB: false})}, expectedResult: []*ScrapeConfig{sc(ScrapeConfigOptions{
JobName: "prometheus",
ScrapeInterval: model.Duration(60 * time.Second),
ScrapeTimeout: model.Duration(10 * time.Second),
ScrapeNativeHistograms: false,
AlwaysScrapeClassicHistograms: false,
ConvertClassicHistToNHCB: false,
})},
}, },
{ {
name: "A global config that only include a scrape config file.", name: "A global config that only include a scrape config file.",
configFile: "testdata/scrape_config_files_only.good.yml", configFile: "testdata/scrape_config_files_only.good.yml",
expectedResult: []*ScrapeConfig{sc(ScrapeConfigOptions{JobName: "prometheus", ScrapeInterval: model.Duration(60 * time.Second), ScrapeTimeout: model.Duration(10 * time.Second), AlwaysScrapeClassicHistograms: false, ConvertClassicHistToNHCB: false})}, expectedResult: []*ScrapeConfig{sc(ScrapeConfigOptions{
JobName: "prometheus",
ScrapeInterval: model.Duration(60 * time.Second),
ScrapeTimeout: model.Duration(10 * time.Second),
ScrapeNativeHistograms: false,
AlwaysScrapeClassicHistograms: false,
ConvertClassicHistToNHCB: false,
})},
}, },
{ {
name: "A global config that combine scrape config files and scrape configs.", name: "A global config that combine scrape config files and scrape configs.",
configFile: "testdata/scrape_config_files_combined.good.yml", configFile: "testdata/scrape_config_files_combined.good.yml",
expectedResult: []*ScrapeConfig{ expectedResult: []*ScrapeConfig{
sc(ScrapeConfigOptions{JobName: "node", ScrapeInterval: model.Duration(60 * time.Second), ScrapeTimeout: model.Duration(10 * time.Second), AlwaysScrapeClassicHistograms: false, ConvertClassicHistToNHCB: false}), sc(ScrapeConfigOptions{
sc(ScrapeConfigOptions{JobName: "prometheus", ScrapeInterval: model.Duration(60 * time.Second), ScrapeTimeout: model.Duration(10 * time.Second), AlwaysScrapeClassicHistograms: false, ConvertClassicHistToNHCB: false}), JobName: "node",
sc(ScrapeConfigOptions{JobName: "alertmanager", ScrapeInterval: model.Duration(60 * time.Second), ScrapeTimeout: model.Duration(10 * time.Second), AlwaysScrapeClassicHistograms: false, ConvertClassicHistToNHCB: false}), ScrapeInterval: model.Duration(60 * time.Second),
ScrapeTimeout: model.Duration(10 * time.Second),
ScrapeNativeHistograms: false,
AlwaysScrapeClassicHistograms: false,
ConvertClassicHistToNHCB: false,
}),
sc(ScrapeConfigOptions{
JobName: "prometheus",
ScrapeInterval: model.Duration(60 * time.Second),
ScrapeTimeout: model.Duration(10 * time.Second),
ScrapeNativeHistograms: false,
AlwaysScrapeClassicHistograms: false,
ConvertClassicHistToNHCB: false,
}),
sc(ScrapeConfigOptions{
JobName: "alertmanager",
ScrapeInterval: model.Duration(60 * time.Second),
ScrapeTimeout: model.Duration(10 * time.Second),
ScrapeNativeHistograms: false,
AlwaysScrapeClassicHistograms: false,
ConvertClassicHistToNHCB: false,
}),
}, },
}, },
{ {
@ -2667,9 +2741,10 @@ func TestGetScrapeConfigs(t *testing.T) {
HonorTimestamps: true, HonorTimestamps: true,
ScrapeInterval: model.Duration(60 * time.Second), ScrapeInterval: model.Duration(60 * time.Second),
ScrapeTimeout: DefaultGlobalConfig.ScrapeTimeout, ScrapeTimeout: DefaultGlobalConfig.ScrapeTimeout,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
MetricNameValidationScheme: model.UTF8Validation, MetricNameValidationScheme: model.UTF8Validation,
MetricNameEscapingScheme: model.AllowUTF8, MetricNameEscapingScheme: model.AllowUTF8,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -2704,9 +2779,10 @@ func TestGetScrapeConfigs(t *testing.T) {
HonorTimestamps: true, HonorTimestamps: true,
ScrapeInterval: model.Duration(15 * time.Second), ScrapeInterval: model.Duration(15 * time.Second),
ScrapeTimeout: DefaultGlobalConfig.ScrapeTimeout, ScrapeTimeout: DefaultGlobalConfig.ScrapeTimeout,
ScrapeProtocols: DefaultGlobalConfig.ScrapeProtocols, ScrapeProtocols: DefaultScrapeProtocols,
MetricNameValidationScheme: model.UTF8Validation, MetricNameValidationScheme: model.UTF8Validation,
MetricNameEscapingScheme: model.AllowUTF8, MetricNameEscapingScheme: model.AllowUTF8,
ScrapeNativeHistograms: boolPtr(false),
AlwaysScrapeClassicHistograms: boolPtr(false), AlwaysScrapeClassicHistograms: boolPtr(false),
ConvertClassicHistogramsToNHCB: boolPtr(false), ConvertClassicHistogramsToNHCB: boolPtr(false),
@ -2791,6 +2867,36 @@ func TestGetScrapeConfigs(t *testing.T) {
configFile: "testdata/local_disable_always_scrape_classic_hist.good.yml", configFile: "testdata/local_disable_always_scrape_classic_hist.good.yml",
expectedResult: []*ScrapeConfig{sc(ScrapeConfigOptions{JobName: "prometheus", ScrapeInterval: model.Duration(60 * time.Second), ScrapeTimeout: model.Duration(10 * time.Second), AlwaysScrapeClassicHistograms: false, ConvertClassicHistToNHCB: false})}, expectedResult: []*ScrapeConfig{sc(ScrapeConfigOptions{JobName: "prometheus", ScrapeInterval: model.Duration(60 * time.Second), ScrapeTimeout: model.Duration(10 * time.Second), AlwaysScrapeClassicHistograms: false, ConvertClassicHistToNHCB: false})},
}, },
{
name: "A global config that enables scrape native histograms",
configFile: "testdata/global_enable_scrape_native_hist.good.yml",
expectedResult: []*ScrapeConfig{sc(ScrapeConfigOptions{JobName: "prometheus", ScrapeInterval: model.Duration(60 * time.Second), ScrapeTimeout: model.Duration(10 * time.Second), ScrapeNativeHistograms: true, ScrapeProtocols: DefaultProtoFirstScrapeProtocols})},
},
{
name: "A global config that enables scrape native histograms and sets scrape protocols explicitly",
configFile: "testdata/global_enable_scrape_native_hist_and_scrape_protocols.good.yml",
expectedResult: []*ScrapeConfig{sc(ScrapeConfigOptions{JobName: "prometheus", ScrapeInterval: model.Duration(60 * time.Second), ScrapeTimeout: model.Duration(10 * time.Second), ScrapeNativeHistograms: true, ScrapeProtocols: []ScrapeProtocol{PrometheusText0_0_4}})},
},
{
name: "A local config that enables scrape native histograms",
configFile: "testdata/local_enable_scrape_native_hist.good.yml",
expectedResult: []*ScrapeConfig{sc(ScrapeConfigOptions{JobName: "prometheus", ScrapeInterval: model.Duration(60 * time.Second), ScrapeTimeout: model.Duration(10 * time.Second), ScrapeNativeHistograms: true, ScrapeProtocols: DefaultProtoFirstScrapeProtocols})},
},
{
name: "A local config that enables scrape native histograms and sets scrape protocols explicitly",
configFile: "testdata/local_enable_scrape_native_hist_and_scrape_protocols.good.yml",
expectedResult: []*ScrapeConfig{sc(ScrapeConfigOptions{JobName: "prometheus", ScrapeInterval: model.Duration(60 * time.Second), ScrapeTimeout: model.Duration(10 * time.Second), ScrapeNativeHistograms: true, ScrapeProtocols: []ScrapeProtocol{PrometheusText0_0_4}})},
},
{
name: "A global config that enables scrape native histograms and scrape config that disables it",
configFile: "testdata/local_disable_scrape_native_hist.good.yml",
expectedResult: []*ScrapeConfig{sc(ScrapeConfigOptions{JobName: "prometheus", ScrapeInterval: model.Duration(60 * time.Second), ScrapeTimeout: model.Duration(10 * time.Second), ScrapeNativeHistograms: false, ScrapeProtocols: DefaultScrapeProtocols})},
},
{
name: "A global config that enables scrape native histograms and scrape protocols and scrape config that disables scrape native histograms but does not change scrape protocols",
configFile: "testdata/global_scrape_protocols_and_local_disable_scrape_native_hist.good.yml",
expectedResult: []*ScrapeConfig{sc(ScrapeConfigOptions{JobName: "prometheus", ScrapeInterval: model.Duration(60 * time.Second), ScrapeTimeout: model.Duration(10 * time.Second), ScrapeNativeHistograms: false, ScrapeProtocols: []ScrapeProtocol{PrometheusText0_0_4}})},
},
} }
for _, tc := range testCases { for _, tc := range testCases {

View File

@ -369,6 +369,7 @@ scrape_configs:
key_file: valid_key_file key_file: valid_key_file
- job_name: hetzner - job_name: hetzner
scrape_native_histograms: true
relabel_configs: relabel_configs:
- action: uppercase - action: uppercase
source_labels: [instance] source_labels: [instance]

View File

@ -0,0 +1,6 @@
global:
scrape_native_histograms: true
scrape_configs:
- job_name: prometheus
static_configs:
- targets: ['localhost:8080']

View File

@ -0,0 +1,7 @@
global:
scrape_native_histograms: true
scrape_protocols: ['PrometheusText0.0.4']
scrape_configs:
- job_name: prometheus
static_configs:
- targets: ['localhost:8080']

View File

@ -0,0 +1,8 @@
global:
scrape_native_histograms: true
scrape_protocols: ['PrometheusText0.0.4']
scrape_configs:
- job_name: prometheus
scrape_native_histograms: false
static_configs:
- targets: ['localhost:8080']

View File

@ -0,0 +1,7 @@
global:
scrape_native_histograms: true
scrape_configs:
- job_name: prometheus
scrape_native_histograms: false
static_configs:
- targets: ['localhost:8080']

View File

@ -0,0 +1,6 @@
global:
scrape_configs:
- job_name: prometheus
scrape_native_histograms: true
static_configs:
- targets: ['localhost:8080']

View File

@ -0,0 +1,7 @@
global:
scrape_configs:
- job_name: prometheus
scrape_native_histograms: true
scrape_protocols: ['PrometheusText0.0.4']
static_configs:
- targets: ['localhost:8080']

View File

@ -62,10 +62,15 @@ global:
# The protocols to negotiate during a scrape with the client. # The protocols to negotiate during a scrape with the client.
# Supported values (case sensitive): PrometheusProto, OpenMetricsText0.0.1, # Supported values (case sensitive): PrometheusProto, OpenMetricsText0.0.1,
# OpenMetricsText1.0.0, PrometheusText0.0.4. # OpenMetricsText1.0.0, PrometheusText0.0.4, PrometheusText1.0.0.
# The default value changes to [ PrometheusProto, OpenMetricsText1.0.0, OpenMetricsText0.0.1, PrometheusText0.0.4 ] # If left unset both here and in an individual scrape config, the
# when native_histogram feature flag is set. # negotiation order used in that scrape config depends on the effective
[ scrape_protocols: [<string>, ...] | default = [ OpenMetricsText1.0.0, OpenMetricsText0.0.1, PrometheusText0.0.4 ] ] # value of scrape_native_histograms for that scrape config.
# If scrape_native_histograms is false, the order is
# [ OpenMetricsText1.0.0, OpenMetricsText0.0.1, PrometheusText1.0.0, PrometheusText0.0.4 ].
# If scrape_native_histograms is true, the order is
# [ PrometheusProto, OpenMetricsText1.0.0, OpenMetricsText0.0.1, PrometheusText1.0.0, PrometheusText0.0.4 ].
[ scrape_protocols: [<string>, ...] ]
# How frequently to evaluate rules. # How frequently to evaluate rules.
[ evaluation_interval: <duration> | default = 1m ] [ evaluation_interval: <duration> | default = 1m ]
@ -138,14 +143,57 @@ global:
# and underscores. # and underscores.
[ metric_name_validation_scheme: <string> | default "utf8" ] [ metric_name_validation_scheme: <string> | default "utf8" ]
# Specifies whether to convert all scraped classic histograms into native # If true, native histograms exposed by a target are recognized during
# histograms with custom buckets. # scraping and ingested as such. If false, any native parts of histograms
[ convert_classic_histograms_to_nhcb: <bool> | default = false] # are ignored and only the classic parts are recognized (possibly as
# a classic histogram with only the +Inf buckets if no explicit classic
# buckets are part of the histogram).
[ scrape_native_histograms: <bool> | default = false ]
# Specifies whether to scrape a classic histogram, even if it is also exposed as a native # Specifies whether to convert scraped classic histograms into native
# histogram (has no effect without --enable-feature=native-histograms). # histograms with custom buckets.
[ convert_classic_histograms_to_nhcb: <bool> | default = false ]
# Specifies whether to additionally scrape the classic parts of a histogram,
# even if it is also exposed with native parts or it is converted into a
# native histogram with custom buckets.
[ always_scrape_classic_histograms: <boolean> | default = false ] [ always_scrape_classic_histograms: <boolean> | default = false ]
# The following explains the various combinations of the last three options
# in various exposition cases.
#
# CASE 1: A histogram is solely exposed as a classic histogram. (Note that
# this also applies if the used scrape protocol (also see the
# scrape_protocols setting) does not support native histograms.) In this
# case, the scrape_native_histograms setting has no effect. If
# convert_classic_histograms_to_nhcb is false, the histogram is ingested as
# a classic histograms. If convert_classic_histograms_to_nhcb is true, the
# histograms is converted to an NHCB. In this case,
# always_scrape_classic_histograms determines whether it is also ingested
# as a classic histograms or not.
#
# CASE 2: A histogram is solely exposed as a native histogram, i.e. it has
# no classic buckets except the optional +Inf bucket but it is marked as a
# native histogram (by some "native parts", at the very least by a no-op
# span). If scrape_native_histograms is false, this case is handled like case
# 1, but the resulting classic histogram or NHCB only has a sole bucket, the
# +Inf bucket. If scrape_native_histograms is true, however, the histogram is
# recognized as a pure native histogram and ingested as such. There will be
# no classic histgram ingested, no matter what
# always_scrape_classic_histograms is set to, and there will be no
# conversion to an NHCB, no matter what convert_classic_histograms_to_nhcb
# is set to.
#
# CASE 3: A histogram is exposed as both a native and a classic histogram,
# i.e. it has "native parts" (at the very least a no-op span) and it has at
# least one classic bucket that is not the +Inf bucket. If
# scrape_native_histograms is false, this case is handled like case 1. The
# native parts are ignored, and there will be either a classic histogram, an
# NHCB, or both. If scrape_native_histograms is true, the histogram is
# ingested as a native histogram. There will be no NHCB, no matter what
# convert_classic_histograms_to_nhcb is set to (it would collide with the
# actual native histogram). However, there will be a classic histogram if (and
# only if) always_scrape_classic_histograms is set to true.
runtime: runtime:
# Configure the Go garbage collector GOGC parameter # Configure the Go garbage collector GOGC parameter
@ -263,7 +311,12 @@ job_name: <job_name>
# The protocols to negotiate during a scrape with the client. # The protocols to negotiate during a scrape with the client.
# Supported values (case sensitive): PrometheusProto, OpenMetricsText0.0.1, # Supported values (case sensitive): PrometheusProto, OpenMetricsText0.0.1,
# OpenMetricsText1.0.0, PrometheusText0.0.4, PrometheusText1.0.0. # OpenMetricsText1.0.0, PrometheusText0.0.4, PrometheusText1.0.0.
[ scrape_protocols: [<string>, ...] | default = <global_config.scrape_protocols> ] # If not set in the global config, the default value depends on the
# setting of scrape_native_histograms. If false, it is
# [ OpenMetricsText1.0.0, OpenMetricsText0.0.1, PrometheusText1.0.0, PrometheusText0.0.4 ].
# If true, it is
# [ PrometheusProto, OpenMetricsText1.0.0, OpenMetricsText0.0.1, PrometheusText1.0.0, PrometheusText0.0.4 ].
[ scrape_protocols: [<string>, ...] | default = <dynamic> ]
# Fallback protocol to use if a scrape returns blank, unparsable, or otherwise # Fallback protocol to use if a scrape returns blank, unparsable, or otherwise
# invalid Content-Type. # invalid Content-Type.
@ -271,11 +324,6 @@ job_name: <job_name>
# OpenMetricsText1.0.0, PrometheusText0.0.4, PrometheusText1.0.0. # OpenMetricsText1.0.0, PrometheusText0.0.4, PrometheusText1.0.0.
[ fallback_scrape_protocol: <string> ] [ fallback_scrape_protocol: <string> ]
# Whether to scrape a classic histogram, even if it is also exposed as a native
# histogram (has no effect without --enable-feature=native-histograms).
[ always_scrape_classic_histograms: <boolean> |
default = <global.always_scrape_classic_histograms> ]
# The HTTP resource path on which to fetch metrics from targets. # The HTTP resource path on which to fetch metrics from targets.
[ metrics_path: <path> | default = /metrics ] [ metrics_path: <path> | default = /metrics ]
@ -570,10 +618,25 @@ metric_relabel_configs:
# schema 8, but might change in the future). # schema 8, but might change in the future).
[ native_histogram_min_bucket_factor: <float> | default = 0 ] [ native_histogram_min_bucket_factor: <float> | default = 0 ]
# If true, native histograms exposed by a target are recognized during
# scraping and ingested as such. If false, any native parts of histograms
# are ignored and only the classic parts are recognized (possibly as
# a classic histogram with only the +Inf buckets if no explicit classic
# buckets are part of the histogram).
[ scrape_native_histograms: <bool> | default = <global.scrape_native_histograms> ]
# Specifies whether to convert classic histograms into native histograms with # Specifies whether to convert classic histograms into native histograms with
# custom buckets (has no effect without --enable-feature=native-histograms). # custom buckets.
[ convert_classic_histograms_to_nhcb: <bool> | default = [ convert_classic_histograms_to_nhcb: <bool> | default = <global.convert_classic_histograms_to_nhcb>]
<global.convert_classic_histograms_to_nhcb>]
# Specifies whether to additionally scrape the classic parts of a histogram,
# even if it is also exposed with native parts or it is converted into a
# native histogram with custom buckets.
[ always_scrape_classic_histograms: <boolean> | default = <global.always_scrape_classic_histograms> ]
# See global configuration above for further explanations of how the last three
# options combine their effects.
``` ```
Where `<job_name>` must be unique across all scrape configurations. Where `<job_name>` must be unique across all scrape configurations.

View File

@ -49,25 +49,15 @@ computed at all.
`--enable-feature=native-histograms` `--enable-feature=native-histograms`
When enabled, Prometheus will ingest native histograms (formerly also known as _This feature flag is being phased out. You should not use it anymore._
sparse histograms or high-res histograms). Native histograms are still highly
experimental. Expect breaking changes to happen (including those rendering the
TSDB unreadable).
Native histograms are currently only supported in the traditional Prometheus Native histograms are a stable feature by now. However, to scrape native
protobuf exposition format. This feature flag therefore also enables a new (and histograms, a scrape config setting `scrape_native_histograms` is required. To
also experimental) protobuf parser, through which _all_ metrics are ingested ease the transition, this feature flag sets the default value of
(i.e. not only native histograms). Prometheus will try to negotiate the `scrape_native_histograms` to `true`. From v3.9 on, this feature flag will be a
protobuf format first. The instrumented target needs to support the protobuf true no-op, and the default value of `scrape_native_histograms` will be always
format, too, _and_ it needs to expose native histograms. The protobuf format `false`. If you are still using this feature flag while running v3.8, update
allows to expose classic and native histograms side by side. With this feature your scrape configs and stop using the feature flag before upgrading to v3.9.
flag disabled, Prometheus will continue to parse the classic histogram (albeit
via the text format). With this flag enabled, Prometheus will still ingest
those classic histograms that do not come with a corresponding native
histogram. However, if a native histogram is present, Prometheus will ignore
the corresponding classic histogram, with the notable exception of exemplars,
which are always ingested. To keep the classic histograms as well, enable
`always_scrape_classic_histograms` in the scrape job.
## Experimental PromQL functions ## Experimental PromQL functions
@ -83,7 +73,12 @@ entirely.
Enables ingestion of created timestamp. Created timestamps are injected as 0 valued samples when appropriate. See [PromCon talk](https://youtu.be/nWf0BfQ5EEA) for details. Enables ingestion of created timestamp. Created timestamps are injected as 0 valued samples when appropriate. See [PromCon talk](https://youtu.be/nWf0BfQ5EEA) for details.
Currently Prometheus supports created timestamps only on the traditional Prometheus Protobuf protocol (WIP for other protocols). As a result, when enabling this feature, the Prometheus protobuf scrape protocol will be prioritized (See `scrape_config.scrape_protocols` settings for more details). Currently Prometheus supports created timestamps only on the traditional
Prometheus Protobuf protocol (WIP for other protocols). Therefore, enabling
this feature pre-sets the global `scrape_protocols` configuration option to
`[ PrometheusProto, OpenMetricsText1.0.0, OpenMetricsText0.0.1, PrometheusText0.0.4 ]`,
resulting in negotiating the Prometheus Protobuf protocol with first priority
(unless the `scrape_protocols` option is set to a different value explicitly).
Besides enabling this feature in Prometheus, created timestamps need to be exposed by the application being scraped. Besides enabling this feature in Prometheus, created timestamps need to be exposed by the application being scraped.
@ -340,4 +335,4 @@ Example query:
For more details, see the [design doc](https://github.com/prometheus/proposals/blob/main/proposals/2025-04-04_extended-range-selectors-semantics.md). For more details, see the [design doc](https://github.com/prometheus/proposals/blob/main/proposals/2025-04-04_extended-range-selectors-semantics.md).
**Note**: Extended Range Selectors are not supported for subqueries. **Note**: Extended Range Selectors are not supported for subqueries.

View File

@ -149,7 +149,7 @@ func benchParse(b *testing.B, data []byte, parser string) {
} }
case "promproto": case "promproto":
newParserFn = func(b []byte, st *labels.SymbolTable) Parser { newParserFn = func(b []byte, st *labels.SymbolTable) Parser {
return NewProtobufParser(b, true, false, false, st) return NewProtobufParser(b, false, true, false, false, st)
} }
case "omtext": case "omtext":
newParserFn = func(b []byte, st *labels.SymbolTable) Parser { newParserFn = func(b []byte, st *labels.SymbolTable) Parser {
@ -276,7 +276,7 @@ func BenchmarkCreatedTimestampPromProto(b *testing.B) {
data := createTestProtoBuf(b).Bytes() data := createTestProtoBuf(b).Bytes()
st := labels.NewSymbolTable() st := labels.NewSymbolTable()
p := NewProtobufParser(data, true, false, false, st) p := NewProtobufParser(data, false, true, false, false, st)
found := false found := false
Inner: Inner:

View File

@ -127,6 +127,17 @@ type ParserOptions struct {
// in the parsed metrics. // in the parsed metrics.
EnableTypeAndUnitLabels bool EnableTypeAndUnitLabels bool
// IgnoreNativeHistograms causes the parser to completely ignore all
// parts of native histograms, but to keep the ability to convert
// classic histograms to NHCB. This has the implication that even a
// histogram that has some native parts but not a single classic bucket
// will be parsed as a classic histogram (with only the +Inf bucket and
// count and sum). Setting this also allows converting a classic
// histogram that already has a native representation to an NHCB. This
// option has no effect on parsers for formats that do not support
// native histograms.
IgnoreNativeHistograms bool
// ConvertClassicHistogramsToNHCB enables conversion of classic histograms // ConvertClassicHistogramsToNHCB enables conversion of classic histograms
// to native histogram custom buckets (NHCB) format. // to native histogram custom buckets (NHCB) format.
ConvertClassicHistogramsToNHCB bool ConvertClassicHistogramsToNHCB bool
@ -168,7 +179,14 @@ func New(b []byte, contentType string, st *labels.SymbolTable, opts ParserOption
o.enableTypeAndUnitLabels = opts.EnableTypeAndUnitLabels o.enableTypeAndUnitLabels = opts.EnableTypeAndUnitLabels
}) })
case "application/vnd.google.protobuf": case "application/vnd.google.protobuf":
return NewProtobufParser(b, opts.KeepClassicOnClassicAndNativeHistograms, opts.ConvertClassicHistogramsToNHCB, opts.EnableTypeAndUnitLabels, st), err return NewProtobufParser(
b,
opts.IgnoreNativeHistograms,
opts.KeepClassicOnClassicAndNativeHistograms,
opts.ConvertClassicHistogramsToNHCB,
opts.EnableTypeAndUnitLabels,
st,
), err
case "text/plain": case "text/plain":
baseParser = NewPromParser(b, st, opts.EnableTypeAndUnitLabels) baseParser = NewPromParser(b, st, opts.EnableTypeAndUnitLabels)
default: default:

View File

@ -77,6 +77,8 @@ type ProtobufParser struct {
// that we have to decode the next MetricDescriptor. // that we have to decode the next MetricDescriptor.
state Entry state Entry
// Whether to completely ignore any native parts of histograms.
ignoreNativeHistograms bool
// Whether to also parse a classic histogram that is also present as a // Whether to also parse a classic histogram that is also present as a
// native histogram. // native histogram.
parseClassicHistograms bool parseClassicHistograms bool
@ -93,7 +95,11 @@ type ProtobufParser struct {
} }
// NewProtobufParser returns a parser for the payload in the byte slice. // NewProtobufParser returns a parser for the payload in the byte slice.
func NewProtobufParser(b []byte, parseClassicHistograms, convertClassicHistogramsToNHCB, enableTypeAndUnitLabels bool, st *labels.SymbolTable) Parser { func NewProtobufParser(
b []byte,
ignoreNativeHistograms, parseClassicHistograms, convertClassicHistogramsToNHCB, enableTypeAndUnitLabels bool,
st *labels.SymbolTable,
) Parser {
builder := labels.NewScratchBuilderWithSymbolTable(st, 16) builder := labels.NewScratchBuilderWithSymbolTable(st, 16)
builder.SetUnsafeAdd(true) builder.SetUnsafeAdd(true)
return &ProtobufParser{ return &ProtobufParser{
@ -102,6 +108,7 @@ func NewProtobufParser(b []byte, parseClassicHistograms, convertClassicHistogram
builder: builder, builder: builder,
state: EntryInvalid, state: EntryInvalid,
ignoreNativeHistograms: ignoreNativeHistograms,
parseClassicHistograms: parseClassicHistograms, parseClassicHistograms: parseClassicHistograms,
enableTypeAndUnitLabels: enableTypeAndUnitLabels, enableTypeAndUnitLabels: enableTypeAndUnitLabels,
convertClassicHistogramsToNHCB: convertClassicHistogramsToNHCB, convertClassicHistogramsToNHCB: convertClassicHistogramsToNHCB,
@ -196,7 +203,7 @@ func (p *ProtobufParser) Histogram() ([]byte, *int64, *histogram.Histogram, *his
h = p.dec.GetHistogram() h = p.dec.GetHistogram()
) )
if !isNativeHistogram(h) { if p.ignoreNativeHistograms || !isNativeHistogram(h) {
// This only happens if we have a classic histogram and // This only happens if we have a classic histogram and
// we converted it to NHCB already in Next. // we converted it to NHCB already in Next.
if *ts != 0 { if *ts != 0 {
@ -494,7 +501,7 @@ func (p *ProtobufParser) Next() (Entry, error) {
case EntryType: case EntryType:
t := p.dec.GetType() t := p.dec.GetType()
if t == dto.MetricType_HISTOGRAM || t == dto.MetricType_GAUGE_HISTOGRAM { if t == dto.MetricType_HISTOGRAM || t == dto.MetricType_GAUGE_HISTOGRAM {
if !isNativeHistogram(p.dec.GetHistogram()) { if p.ignoreNativeHistograms || !isNativeHistogram(p.dec.GetHistogram()) {
p.state = EntrySeries p.state = EntrySeries
p.fieldPos = -3 // We have not returned anything, let p.Next() increment it to -2. p.fieldPos = -3 // We have not returned anything, let p.Next() increment it to -2.
return p.Next() return p.Next()
@ -515,7 +522,8 @@ func (p *ProtobufParser) Next() (Entry, error) {
t == dto.MetricType_GAUGE_HISTOGRAM { t == dto.MetricType_GAUGE_HISTOGRAM {
// Non-trivial series (complex metrics, with magic suffixes). // Non-trivial series (complex metrics, with magic suffixes).
isClassicHistogram := (t == dto.MetricType_HISTOGRAM || t == dto.MetricType_GAUGE_HISTOGRAM) && !isNativeHistogram(p.dec.GetHistogram()) isClassicHistogram := (t == dto.MetricType_HISTOGRAM || t == dto.MetricType_GAUGE_HISTOGRAM) &&
(p.ignoreNativeHistograms || !isNativeHistogram(p.dec.GetHistogram()))
skipSeries := p.convertClassicHistogramsToNHCB && isClassicHistogram && !p.parseClassicHistograms skipSeries := p.convertClassicHistogramsToNHCB && isClassicHistogram && !p.parseClassicHistograms
// Did we iterate over all the classic representations fields? // Did we iterate over all the classic representations fields?
@ -591,10 +599,11 @@ func (p *ProtobufParser) Next() (Entry, error) {
return EntryInvalid, err return EntryInvalid, err
} }
// If this is a metric family does not contain native // If this metric is not a native histograms or we are ignoring
// histograms, it means we are here thanks to NHCB conversion. // native histograms, it means we are here thanks to NHCB
// Return to classic histograms for the consistent flow. // conversion. Return to classic histograms for the consistent
if !isNativeHistogram(p.dec.GetHistogram()) { // flow.
if p.ignoreNativeHistograms || !isNativeHistogram(p.dec.GetHistogram()) {
return switchToClassic() return switchToClassic()
} }

File diff suppressed because it is too large Load Diff

View File

@ -3960,7 +3960,6 @@ func TestInconsistentHistogramCount(t *testing.T) {
dir := t.TempDir() dir := t.TempDir()
opts := tsdb.DefaultHeadOptions() opts := tsdb.DefaultHeadOptions()
opts.EnableNativeHistograms.Store(true)
opts.ChunkDirRoot = dir opts.ChunkDirRoot = dir
// We use TSDB head only. By using full TSDB DB, and appending samples to it, closing it would cause unnecessary HEAD compaction, which slows down the test. // We use TSDB head only. By using full TSDB DB, and appending samples to it, closing it would cause unnecessary HEAD compaction, which slows down the test.
head, err := tsdb.NewHead(nil, nil, nil, nil, opts, nil) head, err := tsdb.NewHead(nil, nil, nil, nil, opts, nil)

View File

@ -86,8 +86,6 @@ type Options struct {
// Option to enable the ingestion of the created timestamp as a synthetic zero sample. // Option to enable the ingestion of the created timestamp as a synthetic zero sample.
// See: https://github.com/prometheus/proposals/blob/main/proposals/2023-06-13_created-timestamp.md // See: https://github.com/prometheus/proposals/blob/main/proposals/2023-06-13_created-timestamp.md
EnableCreatedTimestampZeroIngestion bool EnableCreatedTimestampZeroIngestion bool
// Option to enable the ingestion of native histograms.
EnableNativeHistogramsIngestion bool
// EnableTypeAndUnitLabels // EnableTypeAndUnitLabels
EnableTypeAndUnitLabels bool EnableTypeAndUnitLabels bool

View File

@ -967,7 +967,6 @@ func TestManagerCTZeroIngestionHistogram(t *testing.T) {
app := &collectResultAppender{} app := &collectResultAppender{}
discoveryManager, scrapeManager := runManagers(t, ctx, &Options{ discoveryManager, scrapeManager := runManagers(t, ctx, &Options{
EnableCreatedTimestampZeroIngestion: tc.enableCTZeroIngestion, EnableCreatedTimestampZeroIngestion: tc.enableCTZeroIngestion,
EnableNativeHistogramsIngestion: true,
skipOffsetting: true, skipOffsetting: true,
}, &collectResultAppendable{app}) }, &collectResultAppendable{app})
defer scrapeManager.Stop() defer scrapeManager.Stop()
@ -1007,6 +1006,7 @@ global:
scrape_configs: scrape_configs:
- job_name: test - job_name: test
scrape_native_histograms: true
static_configs: static_configs:
- targets: ['%s'] - targets: ['%s']
`, serverURL.Host) `, serverURL.Host)
@ -1087,7 +1087,6 @@ func TestNHCBAndCTZeroIngestion(t *testing.T) {
app := &collectResultAppender{} app := &collectResultAppender{}
discoveryManager, scrapeManager := runManagers(t, ctx, &Options{ discoveryManager, scrapeManager := runManagers(t, ctx, &Options{
EnableCreatedTimestampZeroIngestion: true, EnableCreatedTimestampZeroIngestion: true,
EnableNativeHistogramsIngestion: true,
skipOffsetting: true, skipOffsetting: true,
}, &collectResultAppendable{app}) }, &collectResultAppendable{app})
defer scrapeManager.Stop() defer scrapeManager.Stop()

View File

@ -131,6 +131,7 @@ type scrapeLoopOptions struct {
trackTimestampsStaleness bool trackTimestampsStaleness bool
interval time.Duration interval time.Duration
timeout time.Duration timeout time.Duration
scrapeNativeHist bool
alwaysScrapeClassicHist bool alwaysScrapeClassicHist bool
convertClassicHistToNHCB bool convertClassicHistToNHCB bool
fallbackScrapeProtocol string fallbackScrapeProtocol string
@ -212,7 +213,7 @@ func newScrapePool(cfg *config.ScrapeConfig, app storage.Appendable, offsetSeed
opts.timeout, opts.timeout,
opts.alwaysScrapeClassicHist, opts.alwaysScrapeClassicHist,
opts.convertClassicHistToNHCB, opts.convertClassicHistToNHCB,
options.EnableNativeHistogramsIngestion, cfg.ScrapeNativeHistogramsEnabled(),
options.EnableCreatedTimestampZeroIngestion, options.EnableCreatedTimestampZeroIngestion,
options.EnableTypeAndUnitLabels, options.EnableTypeAndUnitLabels,
options.ExtraMetrics, options.ExtraMetrics,
@ -371,6 +372,7 @@ func (sp *scrapePool) restartLoops(reuseCache bool) {
trackTimestampsStaleness = sp.config.TrackTimestampsStaleness trackTimestampsStaleness = sp.config.TrackTimestampsStaleness
mrc = sp.config.MetricRelabelConfigs mrc = sp.config.MetricRelabelConfigs
fallbackScrapeProtocol = sp.config.ScrapeFallbackProtocol.HeaderMediaType() fallbackScrapeProtocol = sp.config.ScrapeFallbackProtocol.HeaderMediaType()
scrapeNativeHist = sp.config.ScrapeNativeHistogramsEnabled()
alwaysScrapeClassicHist = sp.config.AlwaysScrapeClassicHistogramsEnabled() alwaysScrapeClassicHist = sp.config.AlwaysScrapeClassicHistogramsEnabled()
convertClassicHistToNHCB = sp.config.ConvertClassicHistogramsToNHCBEnabled() convertClassicHistToNHCB = sp.config.ConvertClassicHistogramsToNHCBEnabled()
) )
@ -415,6 +417,7 @@ func (sp *scrapePool) restartLoops(reuseCache bool) {
interval: targetInterval, interval: targetInterval,
timeout: targetTimeout, timeout: targetTimeout,
fallbackScrapeProtocol: fallbackScrapeProtocol, fallbackScrapeProtocol: fallbackScrapeProtocol,
scrapeNativeHist: scrapeNativeHist,
alwaysScrapeClassicHist: alwaysScrapeClassicHist, alwaysScrapeClassicHist: alwaysScrapeClassicHist,
convertClassicHistToNHCB: convertClassicHistToNHCB, convertClassicHistToNHCB: convertClassicHistToNHCB,
}) })
@ -527,6 +530,7 @@ func (sp *scrapePool) sync(targets []*Target) {
trackTimestampsStaleness = sp.config.TrackTimestampsStaleness trackTimestampsStaleness = sp.config.TrackTimestampsStaleness
mrc = sp.config.MetricRelabelConfigs mrc = sp.config.MetricRelabelConfigs
fallbackScrapeProtocol = sp.config.ScrapeFallbackProtocol.HeaderMediaType() fallbackScrapeProtocol = sp.config.ScrapeFallbackProtocol.HeaderMediaType()
scrapeNativeHist = sp.config.ScrapeNativeHistogramsEnabled()
alwaysScrapeClassicHist = sp.config.AlwaysScrapeClassicHistogramsEnabled() alwaysScrapeClassicHist = sp.config.AlwaysScrapeClassicHistogramsEnabled()
convertClassicHistToNHCB = sp.config.ConvertClassicHistogramsToNHCBEnabled() convertClassicHistToNHCB = sp.config.ConvertClassicHistogramsToNHCBEnabled()
) )
@ -564,6 +568,7 @@ func (sp *scrapePool) sync(targets []*Target) {
mrc: mrc, mrc: mrc,
interval: interval, interval: interval,
timeout: timeout, timeout: timeout,
scrapeNativeHist: scrapeNativeHist,
alwaysScrapeClassicHist: alwaysScrapeClassicHist, alwaysScrapeClassicHist: alwaysScrapeClassicHist,
convertClassicHistToNHCB: convertClassicHistToNHCB, convertClassicHistToNHCB: convertClassicHistToNHCB,
fallbackScrapeProtocol: fallbackScrapeProtocol, fallbackScrapeProtocol: fallbackScrapeProtocol,
@ -939,8 +944,7 @@ type scrapeLoop struct {
enableTypeAndUnitLabels bool enableTypeAndUnitLabels bool
fallbackScrapeProtocol string fallbackScrapeProtocol string
// Feature flagged options. enableNativeHistogramScraping bool
enableNativeHistogramIngestion bool
appender func(ctx context.Context) storage.Appender appender func(ctx context.Context) storage.Appender
symbolTable *labels.SymbolTable symbolTable *labels.SymbolTable
@ -1248,7 +1252,7 @@ func newScrapeLoop(ctx context.Context,
timeout time.Duration, timeout time.Duration,
alwaysScrapeClassicHist bool, alwaysScrapeClassicHist bool,
convertClassicHistToNHCB bool, convertClassicHistToNHCB bool,
enableNativeHistogramIngestion bool, enableNativeHistogramScraping bool,
enableCTZeroIngestion bool, enableCTZeroIngestion bool,
enableTypeAndUnitLabels bool, enableTypeAndUnitLabels bool,
reportExtraMetrics bool, reportExtraMetrics bool,
@ -1283,39 +1287,39 @@ func newScrapeLoop(ctx context.Context,
} }
sl := &scrapeLoop{ sl := &scrapeLoop{
scraper: sc, scraper: sc,
buffers: buffers, buffers: buffers,
cache: cache, cache: cache,
appender: appender, appender: appender,
symbolTable: symbolTable, symbolTable: symbolTable,
sampleMutator: sampleMutator, sampleMutator: sampleMutator,
reportSampleMutator: reportSampleMutator, reportSampleMutator: reportSampleMutator,
stopped: make(chan struct{}), stopped: make(chan struct{}),
offsetSeed: offsetSeed, offsetSeed: offsetSeed,
l: l, l: l,
parentCtx: ctx, parentCtx: ctx,
appenderCtx: appenderCtx, appenderCtx: appenderCtx,
honorTimestamps: honorTimestamps, honorTimestamps: honorTimestamps,
trackTimestampsStaleness: trackTimestampsStaleness, trackTimestampsStaleness: trackTimestampsStaleness,
enableCompression: enableCompression, enableCompression: enableCompression,
sampleLimit: sampleLimit, sampleLimit: sampleLimit,
bucketLimit: bucketLimit, bucketLimit: bucketLimit,
maxSchema: maxSchema, maxSchema: maxSchema,
labelLimits: labelLimits, labelLimits: labelLimits,
interval: interval, interval: interval,
timeout: timeout, timeout: timeout,
alwaysScrapeClassicHist: alwaysScrapeClassicHist, alwaysScrapeClassicHist: alwaysScrapeClassicHist,
convertClassicHistToNHCB: convertClassicHistToNHCB, convertClassicHistToNHCB: convertClassicHistToNHCB,
enableCTZeroIngestion: enableCTZeroIngestion, enableCTZeroIngestion: enableCTZeroIngestion,
enableTypeAndUnitLabels: enableTypeAndUnitLabels, enableTypeAndUnitLabels: enableTypeAndUnitLabels,
fallbackScrapeProtocol: fallbackScrapeProtocol, fallbackScrapeProtocol: fallbackScrapeProtocol,
enableNativeHistogramIngestion: enableNativeHistogramIngestion, enableNativeHistogramScraping: enableNativeHistogramScraping,
reportExtraMetrics: reportExtraMetrics, reportExtraMetrics: reportExtraMetrics,
appendMetadataToWAL: appendMetadataToWAL, appendMetadataToWAL: appendMetadataToWAL,
metrics: metrics, metrics: metrics,
skipOffsetting: skipOffsetting, skipOffsetting: skipOffsetting,
validationScheme: validationScheme, validationScheme: validationScheme,
escapingScheme: escapingScheme, escapingScheme: escapingScheme,
} }
sl.ctx, sl.cancel = context.WithCancel(ctx) sl.ctx, sl.cancel = context.WithCancel(ctx)
@ -1637,6 +1641,7 @@ func (sl *scrapeLoop) append(app storage.Appender, b []byte, contentType string,
p, err := textparse.New(b, contentType, sl.symbolTable, textparse.ParserOptions{ p, err := textparse.New(b, contentType, sl.symbolTable, textparse.ParserOptions{
EnableTypeAndUnitLabels: sl.enableTypeAndUnitLabels, EnableTypeAndUnitLabels: sl.enableTypeAndUnitLabels,
IgnoreNativeHistograms: !sl.enableNativeHistogramScraping,
ConvertClassicHistogramsToNHCB: sl.convertClassicHistToNHCB, ConvertClassicHistogramsToNHCB: sl.convertClassicHistToNHCB,
KeepClassicOnClassicAndNativeHistograms: sl.alwaysScrapeClassicHist, KeepClassicOnClassicAndNativeHistograms: sl.alwaysScrapeClassicHist,
OpenMetricsSkipCTSeries: sl.enableCTZeroIngestion, OpenMetricsSkipCTSeries: sl.enableCTZeroIngestion,
@ -1663,8 +1668,8 @@ func (sl *scrapeLoop) append(app storage.Appender, b []byte, contentType string,
appErrs = appendErrors{} appErrs = appendErrors{}
sampleLimitErr error sampleLimitErr error
bucketLimitErr error bucketLimitErr error
lset labels.Labels // escapes to heap so hoisted out of loop lset labels.Labels // Escapes to heap so hoisted out of loop.
e exemplar.Exemplar // escapes to heap so hoisted out of loop e exemplar.Exemplar // Escapes to heap so hoisted out of loop.
lastMeta *metaEntry lastMeta *metaEntry
lastMFName []byte lastMFName []byte
) )
@ -1734,7 +1739,7 @@ loop:
t = *parsedTimestamp t = *parsedTimestamp
} }
if sl.cache.getDropped(met) || isHistogram && !sl.enableNativeHistogramIngestion { if sl.cache.getDropped(met) {
continue continue
} }
ce, seriesCached, seriesAlreadyScraped := sl.cache.get(met) ce, seriesCached, seriesAlreadyScraped := sl.cache.get(met)

View File

@ -2188,7 +2188,7 @@ func TestScrapeLoop_HistogramBucketLimit(t *testing.T) {
app := &bucketLimitAppender{Appender: resApp, limit: 2} app := &bucketLimitAppender{Appender: resApp, limit: 2}
sl := newBasicScrapeLoop(t, context.Background(), nil, func(context.Context) storage.Appender { return app }, 0) sl := newBasicScrapeLoop(t, context.Background(), nil, func(context.Context) storage.Appender { return app }, 0)
sl.enableNativeHistogramIngestion = true sl.enableNativeHistogramScraping = true
sl.sampleMutator = func(l labels.Labels) labels.Labels { sl.sampleMutator = func(l labels.Labels) labels.Labels {
if l.Has("deleteme") { if l.Has("deleteme") {
return labels.EmptyLabels() return labels.EmptyLabels()
@ -2929,6 +2929,11 @@ metric: <
> >
`, `,
floats: []floatSample{
{metric: labels.FromStrings("__name__", "test_histogram_count"), t: 1234568, f: 175},
{metric: labels.FromStrings("__name__", "test_histogram_sum"), t: 1234568, f: 0.0008280461746287094},
{metric: labels.FromStrings("__name__", "test_histogram_bucket", "le", "+Inf"), t: 1234568, f: 175},
},
}, },
} }
@ -2941,7 +2946,7 @@ metric: <
} }
sl := newBasicScrapeLoop(t, context.Background(), nil, func(context.Context) storage.Appender { return app }, 0) sl := newBasicScrapeLoop(t, context.Background(), nil, func(context.Context) storage.Appender { return app }, 0)
sl.enableNativeHistogramIngestion = test.enableNativeHistogramsIngestion sl.enableNativeHistogramScraping = test.enableNativeHistogramsIngestion
sl.sampleMutator = func(l labels.Labels) labels.Labels { sl.sampleMutator = func(l labels.Labels) labels.Labels {
return mutateSampleLabels(l, discoveryLabels, false, nil) return mutateSampleLabels(l, discoveryLabels, false, nil)
} }
@ -4832,7 +4837,7 @@ metric: <
sl := newBasicScrapeLoop(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return simpleStorage.Appender(ctx) }, 0) sl := newBasicScrapeLoop(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return simpleStorage.Appender(ctx) }, 0)
sl.alwaysScrapeClassicHist = tc.alwaysScrapeClassicHistograms sl.alwaysScrapeClassicHist = tc.alwaysScrapeClassicHistograms
sl.convertClassicHistToNHCB = tc.convertClassicHistToNHCB sl.convertClassicHistToNHCB = tc.convertClassicHistToNHCB
sl.enableNativeHistogramIngestion = true sl.enableNativeHistogramScraping = true
app := simpleStorage.Appender(context.Background()) app := simpleStorage.Appender(context.Background())
var content []byte var content []byte
@ -5349,6 +5354,7 @@ global:
scrape_timeout: 25ms scrape_timeout: 25ms
scrape_configs: scrape_configs:
- job_name: test - job_name: test
scrape_native_histograms: true
%s %s
static_configs: static_configs:
- targets: [%s] - targets: [%s]
@ -5356,10 +5362,9 @@ scrape_configs:
s := teststorage.New(t) s := teststorage.New(t)
defer s.Close() defer s.Close()
s.EnableNativeHistograms()
reg := prometheus.NewRegistry() reg := prometheus.NewRegistry()
mng, err := NewManager(&Options{DiscoveryReloadInterval: model.Duration(10 * time.Millisecond), EnableNativeHistogramsIngestion: true}, nil, nil, s, reg) mng, err := NewManager(&Options{DiscoveryReloadInterval: model.Duration(10 * time.Millisecond)}, nil, nil, s, reg)
require.NoError(t, err) require.NoError(t, err)
cfg, err := config.Load(configStr, promslog.NewNopLogger()) cfg, err := config.Load(configStr, promslog.NewNopLogger())
require.NoError(t, err) require.NoError(t, err)

View File

@ -400,7 +400,6 @@ func testCombinedAppenderOnTSDB(t *testing.T, ingestCTZeroSample bool) {
opts := tsdb.DefaultOptions() opts := tsdb.DefaultOptions()
opts.EnableExemplarStorage = true opts.EnableExemplarStorage = true
opts.MaxExemplars = 100 opts.MaxExemplars = 100
opts.EnableNativeHistograms = true
db, err := tsdb.Open(dir, promslog.NewNopLogger(), prometheus.NewRegistry(), opts, nil) db, err := tsdb.Open(dir, promslog.NewNopLogger(), prometheus.NewRegistry(), opts, nil)
require.NoError(t, err) require.NoError(t, err)

View File

@ -871,7 +871,6 @@ func TestHistogramValidationErrorHandling(t *testing.T) {
t.Run(testName, func(t *testing.T) { t.Run(testName, func(t *testing.T) {
dir := t.TempDir() dir := t.TempDir()
opts := tsdb.DefaultOptions() opts := tsdb.DefaultOptions()
opts.EnableNativeHistograms = true
db, err := tsdb.Open(dir, nil, nil, opts, nil) db, err := tsdb.Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)

View File

@ -71,7 +71,6 @@ func (w *BlockWriter) initHead() error {
opts := DefaultHeadOptions() opts := DefaultHeadOptions()
opts.ChunkRange = w.blockSize opts.ChunkRange = w.blockSize
opts.ChunkDirRoot = w.chunkDir opts.ChunkDirRoot = w.chunkDir
opts.EnableNativeHistograms.Store(true)
h, err := NewHead(nil, w.logger, nil, nil, opts, NewHeadStats()) h, err := NewHead(nil, w.logger, nil, nil, opts, NewHeadStats())
if err != nil { if err != nil {
return fmt.Errorf("tsdb.NewHead: %w", err) return fmt.Errorf("tsdb.NewHead: %w", err)

View File

@ -176,9 +176,6 @@ type Options struct {
// Disables isolation between reads and in-flight appends. // Disables isolation between reads and in-flight appends.
IsolationDisabled bool IsolationDisabled bool
// EnableNativeHistograms enables the ingestion of native histograms.
EnableNativeHistograms bool
// OutOfOrderTimeWindow specifies how much out of order is allowed, if any. // OutOfOrderTimeWindow specifies how much out of order is allowed, if any.
// This can change during run-time, so this value from here should only be used // This can change during run-time, so this value from here should only be used
// while initialising. // while initialising.
@ -964,7 +961,6 @@ func open(dir string, l *slog.Logger, r prometheus.Registerer, opts *Options, rn
headOpts.EnableExemplarStorage = opts.EnableExemplarStorage headOpts.EnableExemplarStorage = opts.EnableExemplarStorage
headOpts.MaxExemplars.Store(opts.MaxExemplars) headOpts.MaxExemplars.Store(opts.MaxExemplars)
headOpts.EnableMemorySnapshotOnShutdown = opts.EnableMemorySnapshotOnShutdown headOpts.EnableMemorySnapshotOnShutdown = opts.EnableMemorySnapshotOnShutdown
headOpts.EnableNativeHistograms.Store(opts.EnableNativeHistograms)
headOpts.OutOfOrderTimeWindow.Store(opts.OutOfOrderTimeWindow) headOpts.OutOfOrderTimeWindow.Store(opts.OutOfOrderTimeWindow)
headOpts.OutOfOrderCapMax.Store(opts.OutOfOrderCapMax) headOpts.OutOfOrderCapMax.Store(opts.OutOfOrderCapMax)
headOpts.EnableSharding = opts.EnableSharding headOpts.EnableSharding = opts.EnableSharding
@ -1191,16 +1187,6 @@ func (db *DB) ApplyConfig(conf *config.Config) error {
return nil return nil
} }
// EnableNativeHistograms enables the native histogram feature.
func (db *DB) EnableNativeHistograms() {
db.head.EnableNativeHistograms()
}
// DisableNativeHistograms disables the native histogram feature.
func (db *DB) DisableNativeHistograms() {
db.head.DisableNativeHistograms()
}
// dbAppender wraps the DB's head appender and triggers compactions on commit // dbAppender wraps the DB's head appender and triggers compactions on commit
// if necessary. // if necessary.
type dbAppender struct { type dbAppender struct {

View File

@ -86,7 +86,6 @@ func openTestDB(t testing.TB, opts *Options, rngs []int64) (db *DB) {
if opts == nil { if opts == nil {
opts = DefaultOptions() opts = DefaultOptions()
} }
opts.EnableNativeHistograms = true
if len(rngs) == 0 { if len(rngs) == 0 {
db, err = Open(tmpdir, nil, nil, opts, nil) db, err = Open(tmpdir, nil, nil, opts, nil)
@ -4517,7 +4516,6 @@ func testOOOWALWrite(t *testing.T,
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
db.EnableNativeHistograms()
t.Cleanup(func() { t.Cleanup(func() {
require.NoError(t, db.Close()) require.NoError(t, db.Close())
@ -4934,7 +4932,6 @@ func TestMultipleEncodingsCommitOrder(t *testing.T) {
db := openTestDB(t, opts, nil) db := openTestDB(t, opts, nil)
db.DisableCompactions() db.DisableCompactions()
db.EnableNativeHistograms()
defer func() { defer func() {
require.NoError(t, db.Close()) require.NoError(t, db.Close())
}() }()
@ -5087,7 +5084,6 @@ func testOOOCompaction(t *testing.T, scenario sampleTypeScenario, addExtraSample
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderCapMax = 30 opts.OutOfOrderCapMax = 30
opts.OutOfOrderTimeWindow = 300 * time.Minute.Milliseconds() opts.OutOfOrderTimeWindow = 300 * time.Minute.Milliseconds()
opts.EnableNativeHistograms = true
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
@ -5295,7 +5291,6 @@ func testOOOCompactionWithNormalCompaction(t *testing.T, scenario sampleTypeScen
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
db.DisableCompactions() // We want to manually call it. db.DisableCompactions() // We want to manually call it.
db.EnableNativeHistograms()
t.Cleanup(func() { t.Cleanup(func() {
require.NoError(t, db.Close()) require.NoError(t, db.Close())
}) })
@ -5403,12 +5398,10 @@ func testOOOCompactionWithDisabledWriteLog(t *testing.T, scenario sampleTypeScen
opts.OutOfOrderCapMax = 30 opts.OutOfOrderCapMax = 30
opts.OutOfOrderTimeWindow = 300 * time.Minute.Milliseconds() opts.OutOfOrderTimeWindow = 300 * time.Minute.Milliseconds()
opts.WALSegmentSize = -1 // disabled WAL and WBL opts.WALSegmentSize = -1 // disabled WAL and WBL
opts.EnableNativeHistograms = true
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
db.DisableCompactions() // We want to manually call it. db.DisableCompactions() // We want to manually call it.
db.EnableNativeHistograms()
t.Cleanup(func() { t.Cleanup(func() {
require.NoError(t, db.Close()) require.NoError(t, db.Close())
}) })
@ -5515,7 +5508,6 @@ func testOOOQueryAfterRestartWithSnapshotAndRemovedWBL(t *testing.T, scenario sa
opts.OutOfOrderCapMax = 10 opts.OutOfOrderCapMax = 10
opts.OutOfOrderTimeWindow = 300 * time.Minute.Milliseconds() opts.OutOfOrderTimeWindow = 300 * time.Minute.Milliseconds()
opts.EnableMemorySnapshotOnShutdown = true opts.EnableMemorySnapshotOnShutdown = true
opts.EnableNativeHistograms = true
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
@ -5880,7 +5872,6 @@ func testQuerierOOOQuery(t *testing.T,
opts.OutOfOrderCapMax = tc.oooCap opts.OutOfOrderCapMax = tc.oooCap
db := openTestDB(t, opts, nil) db := openTestDB(t, opts, nil)
db.DisableCompactions() db.DisableCompactions()
db.EnableNativeHistograms()
defer func() { defer func() {
require.NoError(t, db.Close()) require.NoError(t, db.Close())
}() }()
@ -6210,7 +6201,6 @@ func testChunkQuerierOOOQuery(t *testing.T,
opts.OutOfOrderCapMax = tc.oooCap opts.OutOfOrderCapMax = tc.oooCap
db := openTestDB(t, opts, nil) db := openTestDB(t, opts, nil)
db.DisableCompactions() db.DisableCompactions()
db.EnableNativeHistograms()
defer func() { defer func() {
require.NoError(t, db.Close()) require.NoError(t, db.Close())
}() }()
@ -6729,7 +6719,6 @@ func testOOOAppendAndQuery(t *testing.T, scenario sampleTypeScenario) {
db := openTestDB(t, opts, nil) db := openTestDB(t, opts, nil)
db.DisableCompactions() db.DisableCompactions()
db.EnableNativeHistograms()
t.Cleanup(func() { t.Cleanup(func() {
require.NoError(t, db.Close()) require.NoError(t, db.Close())
}) })
@ -6861,7 +6850,6 @@ func testOOODisabled(t *testing.T, scenario sampleTypeScenario) {
opts.OutOfOrderTimeWindow = 0 opts.OutOfOrderTimeWindow = 0
db := openTestDB(t, opts, nil) db := openTestDB(t, opts, nil)
db.DisableCompactions() db.DisableCompactions()
db.EnableNativeHistograms()
t.Cleanup(func() { t.Cleanup(func() {
require.NoError(t, db.Close()) require.NoError(t, db.Close())
}) })
@ -6934,7 +6922,6 @@ func testWBLAndMmapReplay(t *testing.T, scenario sampleTypeScenario) {
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderCapMax = 30 opts.OutOfOrderCapMax = 30
opts.OutOfOrderTimeWindow = 4 * time.Hour.Milliseconds() opts.OutOfOrderTimeWindow = 4 * time.Hour.Milliseconds()
opts.EnableNativeHistograms = true
db := openTestDB(t, opts, nil) db := openTestDB(t, opts, nil)
db.DisableCompactions() db.DisableCompactions()
@ -7127,7 +7114,6 @@ func TestOOOHistogramCompactionWithCounterResets(t *testing.T) {
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
db.DisableCompactions() // We want to manually call it. db.DisableCompactions() // We want to manually call it.
db.EnableNativeHistograms()
t.Cleanup(func() { t.Cleanup(func() {
require.NoError(t, db.Close()) require.NoError(t, db.Close())
}) })
@ -7488,7 +7474,6 @@ func TestInterleavedInOrderAndOOOHistogramCompactionWithCounterResets(t *testing
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
db.DisableCompactions() // We want to manually call it. db.DisableCompactions() // We want to manually call it.
db.EnableNativeHistograms()
t.Cleanup(func() { t.Cleanup(func() {
require.NoError(t, db.Close()) require.NoError(t, db.Close())
}) })
@ -7604,7 +7589,6 @@ func testOOOCompactionFailure(t *testing.T, scenario sampleTypeScenario) {
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
db.DisableCompactions() // We want to manually call it. db.DisableCompactions() // We want to manually call it.
db.EnableNativeHistograms()
t.Cleanup(func() { t.Cleanup(func() {
require.NoError(t, db.Close()) require.NoError(t, db.Close())
}) })
@ -7892,7 +7876,6 @@ func testOOOMmapCorruption(t *testing.T, scenario sampleTypeScenario) {
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderCapMax = 10 opts.OutOfOrderCapMax = 10
opts.OutOfOrderTimeWindow = 300 * time.Minute.Milliseconds() opts.OutOfOrderTimeWindow = 300 * time.Minute.Milliseconds()
opts.EnableNativeHistograms = true
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
@ -8027,7 +8010,6 @@ func testOutOfOrderRuntimeConfig(t *testing.T, scenario sampleTypeScenario) {
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderTimeWindow = oooTimeWindow opts.OutOfOrderTimeWindow = oooTimeWindow
opts.EnableNativeHistograms = true
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
@ -8322,7 +8304,6 @@ func testNoGapAfterRestartWithOOO(t *testing.T, scenario sampleTypeScenario) {
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderTimeWindow = 30 * time.Minute.Milliseconds() opts.OutOfOrderTimeWindow = 30 * time.Minute.Milliseconds()
opts.EnableNativeHistograms = true
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
@ -8381,7 +8362,6 @@ func testWblReplayAfterOOODisableAndRestart(t *testing.T, scenario sampleTypeSce
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderTimeWindow = 60 * time.Minute.Milliseconds() opts.OutOfOrderTimeWindow = 60 * time.Minute.Milliseconds()
opts.EnableNativeHistograms = true
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
@ -8449,7 +8429,6 @@ func testPanicOnApplyConfig(t *testing.T, scenario sampleTypeScenario) {
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderTimeWindow = 60 * time.Minute.Milliseconds() opts.OutOfOrderTimeWindow = 60 * time.Minute.Milliseconds()
opts.EnableNativeHistograms = true
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
@ -8509,7 +8488,6 @@ func testDiskFillingUpAfterDisablingOOO(t *testing.T, scenario sampleTypeScenari
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderTimeWindow = 60 * time.Minute.Milliseconds() opts.OutOfOrderTimeWindow = 60 * time.Minute.Milliseconds()
opts.EnableNativeHistograms = true
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
@ -8999,59 +8977,6 @@ func TestQueryHistogramFromBlocksWithCompaction(t *testing.T) {
} }
} }
func TestNativeHistogramFlag(t *testing.T) {
dir := t.TempDir()
db, err := Open(dir, nil, nil, nil, nil)
require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, db.Close())
})
h := &histogram.Histogram{
Count: 9,
ZeroCount: 4,
ZeroThreshold: 0.001,
Sum: 35.5,
Schema: 1,
PositiveSpans: []histogram.Span{
{Offset: 0, Length: 2},
{Offset: 2, Length: 2},
},
PositiveBuckets: []int64{1, 1, -1, 0},
}
l := labels.FromStrings("foo", "bar")
app := db.Appender(context.Background())
// Disabled by default.
_, err = app.AppendHistogram(0, l, 100, h, nil)
require.Equal(t, storage.ErrNativeHistogramsDisabled, err)
_, err = app.AppendHistogram(0, l, 105, nil, h.ToFloat(nil))
require.Equal(t, storage.ErrNativeHistogramsDisabled, err)
// Enable and append.
db.EnableNativeHistograms()
_, err = app.AppendHistogram(0, l, 200, h, nil)
require.NoError(t, err)
_, err = app.AppendHistogram(0, l, 205, nil, h.ToFloat(nil))
require.NoError(t, err)
db.DisableNativeHistograms()
_, err = app.AppendHistogram(0, l, 300, h, nil)
require.Equal(t, storage.ErrNativeHistogramsDisabled, err)
_, err = app.AppendHistogram(0, l, 305, nil, h.ToFloat(nil))
require.Equal(t, storage.ErrNativeHistogramsDisabled, err)
require.NoError(t, app.Commit())
q, err := db.Querier(math.MinInt, math.MaxInt64)
require.NoError(t, err)
act := query(t, q, labels.MustNewMatcher(labels.MatchEqual, "foo", "bar"))
require.Equal(t, map[string][]chunks.Sample{
l.String(): {sample{t: 200, h: h}, sample{t: 205, fh: h.ToFloat(nil)}},
}, act)
}
func TestOOONativeHistogramsSettings(t *testing.T) { func TestOOONativeHistogramsSettings(t *testing.T) {
h := &histogram.Histogram{ h := &histogram.Histogram{
Count: 9, Count: 9,
@ -9076,8 +9001,6 @@ func TestOOONativeHistogramsSettings(t *testing.T) {
require.NoError(t, db.Close()) require.NoError(t, db.Close())
}() }()
db.EnableNativeHistograms()
app := db.Appender(context.Background()) app := db.Appender(context.Background())
_, err := app.AppendHistogram(0, l, 100, h, nil) _, err := app.AppendHistogram(0, l, 100, h, nil)
require.NoError(t, err) require.NoError(t, err)
@ -9094,32 +9017,6 @@ func TestOOONativeHistogramsSettings(t *testing.T) {
l.String(): {sample{t: 100, h: h}}, l.String(): {sample{t: 100, h: h}},
}, act) }, act)
}) })
t.Run("Test OOO Native Histograms if OOO is enabled and Native Histograms are disabled", func(t *testing.T) {
opts := DefaultOptions()
opts.OutOfOrderTimeWindow = 100
db := openTestDB(t, opts, []int64{100})
defer func() {
require.NoError(t, db.Close())
}()
db.DisableNativeHistograms()
// Attempt to add an in-order sample
app := db.Appender(context.Background())
_, err := app.AppendHistogram(0, l, 200, h, nil)
require.Equal(t, storage.ErrNativeHistogramsDisabled, err)
// Attempt to add an OOO sample
_, err = app.AppendHistogram(0, l, 100, h, nil)
require.Equal(t, storage.ErrNativeHistogramsDisabled, err)
require.NoError(t, app.Commit())
q, err := db.Querier(math.MinInt, math.MaxInt64)
require.NoError(t, err)
act := query(t, q, labels.MustNewMatcher(labels.MatchEqual, "foo", "bar"))
require.Equal(t, map[string][]chunks.Sample{}, act)
})
t.Run("Test OOO native histograms when both OOO and Native Histograms are enabled", func(t *testing.T) { t.Run("Test OOO native histograms when both OOO and Native Histograms are enabled", func(t *testing.T) {
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderTimeWindow = 100 opts.OutOfOrderTimeWindow = 100
@ -9128,8 +9025,6 @@ func TestOOONativeHistogramsSettings(t *testing.T) {
require.NoError(t, db.Close()) require.NoError(t, db.Close())
}() }()
db.EnableNativeHistograms()
// Add in-order samples // Add in-order samples
app := db.Appender(context.Background()) app := db.Appender(context.Background())
_, err := app.AppendHistogram(0, l, 200, h, nil) _, err := app.AppendHistogram(0, l, 200, h, nil)

View File

@ -161,9 +161,6 @@ type HeadOptions struct {
OutOfOrderTimeWindow atomic.Int64 OutOfOrderTimeWindow atomic.Int64
OutOfOrderCapMax atomic.Int64 OutOfOrderCapMax atomic.Int64
// EnableNativeHistograms enables the ingestion of native histograms.
EnableNativeHistograms atomic.Bool
ChunkRange int64 ChunkRange int64
// ChunkDirRoot is the parent directory of the chunks directory. // ChunkDirRoot is the parent directory of the chunks directory.
ChunkDirRoot string ChunkDirRoot string
@ -1050,16 +1047,6 @@ func (h *Head) SetOutOfOrderTimeWindow(oooTimeWindow int64, wbl *wlog.WL) {
h.opts.OutOfOrderTimeWindow.Store(oooTimeWindow) h.opts.OutOfOrderTimeWindow.Store(oooTimeWindow)
} }
// EnableNativeHistograms enables the native histogram feature.
func (h *Head) EnableNativeHistograms() {
h.opts.EnableNativeHistograms.Store(true)
}
// DisableNativeHistograms disables the native histogram feature.
func (h *Head) DisableNativeHistograms() {
h.opts.EnableNativeHistograms.Store(false)
}
// PostingsCardinalityStats returns highest cardinality stats by label and value names. // PostingsCardinalityStats returns highest cardinality stats by label and value names.
func (h *Head) PostingsCardinalityStats(statsByLabelName string, limit int) *index.PostingsStats { func (h *Head) PostingsCardinalityStats(statsByLabelName string, limit int) *index.PostingsStats {
cacheKey := statsByLabelName + ";" + strconv.Itoa(limit) cacheKey := statsByLabelName + ";" + strconv.Itoa(limit)

View File

@ -797,10 +797,6 @@ func (a *headAppender) AppendExemplar(ref storage.SeriesRef, lset labels.Labels,
} }
func (a *headAppender) AppendHistogram(ref storage.SeriesRef, lset labels.Labels, t int64, h *histogram.Histogram, fh *histogram.FloatHistogram) (storage.SeriesRef, error) { func (a *headAppender) AppendHistogram(ref storage.SeriesRef, lset labels.Labels, t int64, h *histogram.Histogram, fh *histogram.FloatHistogram) (storage.SeriesRef, error) {
if !a.head.opts.EnableNativeHistograms.Load() {
return 0, storage.ErrNativeHistogramsDisabled
}
// Fail fast if OOO is disabled and the sample is out of bounds. // Fail fast if OOO is disabled and the sample is out of bounds.
// Otherwise a full check will be done later to decide if the sample is in-order or out-of-order. // Otherwise a full check will be done later to decide if the sample is in-order or out-of-order.
if a.oooTimeWindow == 0 && t < a.minValidTime { if a.oooTimeWindow == 0 && t < a.minValidTime {
@ -907,10 +903,6 @@ func (a *headAppender) AppendHistogram(ref storage.SeriesRef, lset labels.Labels
} }
func (a *headAppender) AppendHistogramCTZeroSample(ref storage.SeriesRef, lset labels.Labels, t, ct int64, h *histogram.Histogram, fh *histogram.FloatHistogram) (storage.SeriesRef, error) { func (a *headAppender) AppendHistogramCTZeroSample(ref storage.SeriesRef, lset labels.Labels, t, ct int64, h *histogram.Histogram, fh *histogram.FloatHistogram) (storage.SeriesRef, error) {
if !a.head.opts.EnableNativeHistograms.Load() {
return 0, storage.ErrNativeHistogramsDisabled
}
if ct >= t { if ct >= t {
return 0, storage.ErrCTNewerThanSample return 0, storage.ErrCTNewerThanSample
} }

View File

@ -64,7 +64,6 @@ func newTestHeadDefaultOptions(chunkRange int64, oooEnabled bool) *HeadOptions {
opts.ChunkRange = chunkRange opts.ChunkRange = chunkRange
opts.EnableExemplarStorage = true opts.EnableExemplarStorage = true
opts.MaxExemplars.Store(config.DefaultExemplarsConfig.MaxExemplars) opts.MaxExemplars.Store(config.DefaultExemplarsConfig.MaxExemplars)
opts.EnableNativeHistograms.Store(true)
if oooEnabled { if oooEnabled {
opts.OutOfOrderTimeWindow.Store(10 * time.Minute.Milliseconds()) opts.OutOfOrderTimeWindow.Store(10 * time.Minute.Milliseconds())
} }
@ -3199,7 +3198,6 @@ func TestOutOfOrderSamplesMetric(t *testing.T) {
for name, scenario := range sampleTypeScenarios { for name, scenario := range sampleTypeScenarios {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
options := DefaultOptions() options := DefaultOptions()
options.EnableNativeHistograms = true
testOutOfOrderSamplesMetric(t, scenario, options, storage.ErrOutOfOrderSample) testOutOfOrderSamplesMetric(t, scenario, options, storage.ErrOutOfOrderSample)
}) })
} }
@ -3213,7 +3211,6 @@ func TestOutOfOrderSamplesMetricNativeHistogramOOODisabled(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
options := DefaultOptions() options := DefaultOptions()
options.OutOfOrderTimeWindow = 0 options.OutOfOrderTimeWindow = 0
options.EnableNativeHistograms = true
testOutOfOrderSamplesMetric(t, scenario, options, storage.ErrOutOfOrderSample) testOutOfOrderSamplesMetric(t, scenario, options, storage.ErrOutOfOrderSample)
}) })
} }
@ -4071,7 +4068,6 @@ func testQueryOOOHeadDuringTruncate(t *testing.T, makeQuerier func(db *DB, minT,
dir := t.TempDir() dir := t.TempDir()
opts := DefaultOptions() opts := DefaultOptions()
opts.EnableNativeHistograms = true
opts.OutOfOrderTimeWindow = maxT opts.OutOfOrderTimeWindow = maxT
opts.MinBlockDuration = maxT / 2 // So that head will compact up to 3000. opts.MinBlockDuration = maxT / 2 // So that head will compact up to 3000.
@ -5313,7 +5309,6 @@ func TestOOOHistogramCounterResetHeaders(t *testing.T) {
func TestAppendingDifferentEncodingToSameSeries(t *testing.T) { func TestAppendingDifferentEncodingToSameSeries(t *testing.T) {
dir := t.TempDir() dir := t.TempDir()
opts := DefaultOptions() opts := DefaultOptions()
opts.EnableNativeHistograms = true
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
t.Cleanup(func() { t.Cleanup(func() {
@ -5564,7 +5559,6 @@ func testWBLReplay(t *testing.T, scenario sampleTypeScenario) {
opts.ChunkRange = 1000 opts.ChunkRange = 1000
opts.ChunkDirRoot = dir opts.ChunkDirRoot = dir
opts.OutOfOrderTimeWindow.Store(30 * time.Minute.Milliseconds()) opts.OutOfOrderTimeWindow.Store(30 * time.Minute.Milliseconds())
opts.EnableNativeHistograms.Store(true)
h, err := NewHead(nil, nil, wal, oooWlog, opts, nil) h, err := NewHead(nil, nil, wal, oooWlog, opts, nil)
require.NoError(t, err) require.NoError(t, err)
@ -5658,7 +5652,6 @@ func testOOOMmapReplay(t *testing.T, scenario sampleTypeScenario) {
opts.ChunkDirRoot = dir opts.ChunkDirRoot = dir
opts.OutOfOrderCapMax.Store(30) opts.OutOfOrderCapMax.Store(30)
opts.OutOfOrderTimeWindow.Store(1000 * time.Minute.Milliseconds()) opts.OutOfOrderTimeWindow.Store(1000 * time.Minute.Milliseconds())
opts.EnableNativeHistograms.Store(true)
h, err := NewHead(nil, nil, wal, oooWlog, opts, nil) h, err := NewHead(nil, nil, wal, oooWlog, opts, nil)
require.NoError(t, err) require.NoError(t, err)
@ -5960,7 +5953,6 @@ func testOOOAppendWithNoSeries(t *testing.T, appendFunc func(appender storage.Ap
opts.ChunkDirRoot = dir opts.ChunkDirRoot = dir
opts.OutOfOrderCapMax.Store(30) opts.OutOfOrderCapMax.Store(30)
opts.OutOfOrderTimeWindow.Store(120 * time.Minute.Milliseconds()) opts.OutOfOrderTimeWindow.Store(120 * time.Minute.Milliseconds())
opts.EnableNativeHistograms.Store(true)
h, err := NewHead(nil, nil, wal, oooWlog, opts, nil) h, err := NewHead(nil, nil, wal, oooWlog, opts, nil)
require.NoError(t, err) require.NoError(t, err)
@ -6051,7 +6043,6 @@ func testHeadMinOOOTimeUpdate(t *testing.T, scenario sampleTypeScenario) {
opts := DefaultHeadOptions() opts := DefaultHeadOptions()
opts.ChunkDirRoot = dir opts.ChunkDirRoot = dir
opts.OutOfOrderTimeWindow.Store(10 * time.Minute.Milliseconds()) opts.OutOfOrderTimeWindow.Store(10 * time.Minute.Milliseconds())
opts.EnableNativeHistograms.Store(true)
h, err := NewHead(nil, nil, wal, oooWlog, opts, nil) h, err := NewHead(nil, nil, wal, oooWlog, opts, nil)
require.NoError(t, err) require.NoError(t, err)

View File

@ -493,7 +493,6 @@ func testOOOHeadChunkReader_Chunk(t *testing.T, scenario sampleTypeScenario) {
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderCapMax = 5 opts.OutOfOrderCapMax = 5
opts.OutOfOrderTimeWindow = 120 * time.Minute.Milliseconds() opts.OutOfOrderTimeWindow = 120 * time.Minute.Milliseconds()
opts.EnableNativeHistograms = true
s1 := labels.FromStrings("l", "v1") s1 := labels.FromStrings("l", "v1")
minutes := func(m int64) int64 { return m * time.Minute.Milliseconds() } minutes := func(m int64) int64 { return m * time.Minute.Milliseconds() }
@ -903,7 +902,6 @@ func testOOOHeadChunkReader_Chunk_ConsistentQueryResponseDespiteOfHeadExpanding(
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderCapMax = 5 opts.OutOfOrderCapMax = 5
opts.OutOfOrderTimeWindow = 120 * time.Minute.Milliseconds() opts.OutOfOrderTimeWindow = 120 * time.Minute.Milliseconds()
opts.EnableNativeHistograms = true
s1 := labels.FromStrings("l", "v1") s1 := labels.FromStrings("l", "v1")
minutes := func(m int64) int64 { return m * time.Minute.Milliseconds() } minutes := func(m int64) int64 { return m * time.Minute.Milliseconds() }

View File

@ -3612,7 +3612,6 @@ func TestQueryWithDeletedHistograms(t *testing.T) {
require.NoError(t, db.Close()) require.NoError(t, db.Close())
}() }()
db.EnableNativeHistograms()
appender := db.Appender(context.Background()) appender := db.Appender(context.Background())
var ( var (
@ -3671,7 +3670,6 @@ func TestQueryWithOneChunkCompletelyDeleted(t *testing.T) {
require.NoError(t, db.Close()) require.NoError(t, db.Close())
}() }()
db.EnableNativeHistograms()
appender := db.Appender(context.Background()) appender := db.Appender(context.Background())
var ( var (

View File

@ -50,7 +50,6 @@ func NewWithError(outOfOrderTimeWindow ...int64) (*TestStorage, error) {
opts.MinBlockDuration = int64(24 * time.Hour / time.Millisecond) opts.MinBlockDuration = int64(24 * time.Hour / time.Millisecond)
opts.MaxBlockDuration = int64(24 * time.Hour / time.Millisecond) opts.MaxBlockDuration = int64(24 * time.Hour / time.Millisecond)
opts.RetentionDuration = 0 opts.RetentionDuration = 0
opts.EnableNativeHistograms = true
// Set OutOfOrderTimeWindow if provided, otherwise use default (0) // Set OutOfOrderTimeWindow if provided, otherwise use default (0)
if len(outOfOrderTimeWindow) > 0 { if len(outOfOrderTimeWindow) > 0 {

View File

@ -453,7 +453,7 @@ func TestFederationWithNativeHistograms(t *testing.T) {
require.Equal(t, http.StatusOK, res.Code) require.Equal(t, http.StatusOK, res.Code)
body, err := io.ReadAll(res.Body) body, err := io.ReadAll(res.Body)
require.NoError(t, err) require.NoError(t, err)
p := textparse.NewProtobufParser(body, false, false, false, labels.NewSymbolTable()) p := textparse.NewProtobufParser(body, false, false, false, false, labels.NewSymbolTable())
var actVec promql.Vector var actVec promql.Vector
metricFamilies := 0 metricFamilies := 0
l := labels.Labels{} l := labels.Labels{}