bugfix: Decouple native histogram ingestions and protobuf parsing

Up until this point, if a scrape was done with the protobuf format Prometheus would always try to ingest native histograms even with the feature flag disabled. This causes problems with other feature-flags that depend on the protobuf format, like 'created-timestamp-zero-ingestion'. This commit decouples native histogram parsing from ingestion, making sure ingestion only happens when the 'native-histogram' feature-flag is enabled.

Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com>
This commit is contained in:
Arthur Silva Sens 2024-04-24 10:53:54 -03:00
parent 76b0318ed5
commit 7aacef9b42
No known key found for this signature in database
4 changed files with 57 additions and 38 deletions

View file

@ -217,6 +217,7 @@ func (c *flagConfig) setFeatureListOptions(logger log.Logger) error {
level.Info(logger).Log("msg", "Experimental PromQL functions enabled.") level.Info(logger).Log("msg", "Experimental PromQL functions enabled.")
case "native-histograms": case "native-histograms":
c.tsdb.EnableNativeHistograms = true 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 config.DefaultConfig.GlobalConfig.ScrapeProtocols = config.DefaultProtoFirstScrapeProtocols
config.DefaultGlobalConfig.ScrapeProtocols = config.DefaultProtoFirstScrapeProtocols config.DefaultGlobalConfig.ScrapeProtocols = config.DefaultProtoFirstScrapeProtocols

View file

@ -81,6 +81,8 @@ 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
// Optional HTTP client options to use when scraping. // Optional HTTP client options to use when scraping.
HTTPClientOptions []config_util.HTTPClientOption HTTPClientOptions []config_util.HTTPClientOption

View file

@ -178,6 +178,7 @@ func newScrapePool(cfg *config.ScrapeConfig, app storage.Appendable, offsetSeed
opts.interval, opts.interval,
opts.timeout, opts.timeout,
opts.scrapeClassicHistograms, opts.scrapeClassicHistograms,
options.EnableNativeHistogramsIngestion,
options.EnableCreatedTimestampZeroIngestion, options.EnableCreatedTimestampZeroIngestion,
options.ExtraMetrics, options.ExtraMetrics,
options.EnableMetadataStorage, options.EnableMetadataStorage,
@ -827,6 +828,9 @@ type scrapeLoop struct {
interval time.Duration interval time.Duration
timeout time.Duration timeout time.Duration
scrapeClassicHistograms bool scrapeClassicHistograms bool
// Feature flagged options.
enableNativeHistogramIngestion bool
enableCTZeroIngestion bool enableCTZeroIngestion bool
appender func(ctx context.Context) storage.Appender appender func(ctx context.Context) storage.Appender
@ -1123,6 +1127,7 @@ func newScrapeLoop(ctx context.Context,
interval time.Duration, interval time.Duration,
timeout time.Duration, timeout time.Duration,
scrapeClassicHistograms bool, scrapeClassicHistograms bool,
enableNativeHistogramIngestion bool,
enableCTZeroIngestion bool, enableCTZeroIngestion bool,
reportExtraMetrics bool, reportExtraMetrics bool,
appendMetadataToWAL bool, appendMetadataToWAL bool,
@ -1175,6 +1180,7 @@ func newScrapeLoop(ctx context.Context,
interval: interval, interval: interval,
timeout: timeout, timeout: timeout,
scrapeClassicHistograms: scrapeClassicHistograms, scrapeClassicHistograms: scrapeClassicHistograms,
enableNativeHistogramIngestion: enableNativeHistogramIngestion,
enableCTZeroIngestion: enableCTZeroIngestion, enableCTZeroIngestion: enableCTZeroIngestion,
reportExtraMetrics: reportExtraMetrics, reportExtraMetrics: reportExtraMetrics,
appendMetadataToWAL: appendMetadataToWAL, appendMetadataToWAL: appendMetadataToWAL,
@ -1627,7 +1633,7 @@ loop:
} }
} }
if isHistogram { if isHistogram && sl.enableNativeHistogramIngestion {
if h != nil { if h != nil {
ref, err = app.AppendHistogram(ref, lset, t, h, nil) ref, err = app.AppendHistogram(ref, lset, t, h, nil)
} else { } else {

View file

@ -678,6 +678,7 @@ func newBasicScrapeLoop(t testing.TB, ctx context.Context, scraper scraper, app
false, false,
false, false,
false, false,
false,
nil, nil,
false, false,
newTestScrapeMetrics(t), newTestScrapeMetrics(t),
@ -819,6 +820,7 @@ func TestScrapeLoopRun(t *testing.T) {
false, false,
false, false,
false, false,
false,
nil, nil,
false, false,
scrapeMetrics, scrapeMetrics,
@ -962,6 +964,7 @@ func TestScrapeLoopMetadata(t *testing.T) {
false, false,
false, false,
false, false,
false,
nil, nil,
false, false,
scrapeMetrics, scrapeMetrics,
@ -1571,6 +1574,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(ctx context.Context) storage.Appender { return app }, 0) sl := newBasicScrapeLoop(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return app }, 0)
sl.enableNativeHistogramIngestion = 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()
@ -1799,6 +1803,7 @@ func TestScrapeLoopAppendExemplar(t *testing.T) {
tests := []struct { tests := []struct {
title string title string
scrapeClassicHistograms bool scrapeClassicHistograms bool
enableNativeHistogramsIngestion bool
scrapeText string scrapeText string
contentType string contentType string
discoveryLabels []string discoveryLabels []string
@ -1862,6 +1867,8 @@ metric_total{n="2"} 2 # {t="2"} 2.0 20000
}, },
{ {
title: "Native histogram with three exemplars", title: "Native histogram with three exemplars",
enableNativeHistogramsIngestion: true,
scrapeText: `name: "test_histogram" scrapeText: `name: "test_histogram"
help: "Test histogram with many buckets removed to keep it manageable in size." help: "Test histogram with many buckets removed to keep it manageable in size."
type: HISTOGRAM type: HISTOGRAM
@ -1976,6 +1983,8 @@ metric: <
}, },
{ {
title: "Native histogram with three exemplars scraped as classic histogram", title: "Native histogram with three exemplars scraped as classic histogram",
enableNativeHistogramsIngestion: true,
scrapeText: `name: "test_histogram" scrapeText: `name: "test_histogram"
help: "Test histogram with many buckets removed to keep it manageable in size." help: "Test histogram with many buckets removed to keep it manageable in size."
type: HISTOGRAM type: HISTOGRAM
@ -2115,6 +2124,7 @@ metric: <
} }
sl := newBasicScrapeLoop(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return app }, 0) sl := newBasicScrapeLoop(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return app }, 0)
sl.enableNativeHistogramIngestion = 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)
} }
@ -3710,7 +3720,7 @@ scrape_configs:
s.DB.EnableNativeHistograms() s.DB.EnableNativeHistograms()
reg := prometheus.NewRegistry() reg := prometheus.NewRegistry()
mng, err := NewManager(nil, nil, s, reg) mng, err := NewManager(&Options{EnableNativeHistogramsIngestion: true}, nil, s, reg)
require.NoError(t, err) require.NoError(t, err)
cfg, err := config.Load(configStr, false, log.NewNopLogger()) cfg, err := config.Load(configStr, false, log.NewNopLogger())
require.NoError(t, err) require.NoError(t, err)