diff --git a/CHANGELOG.md b/CHANGELOG.md index 9df080b7b79..8d4b73ada42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,7 @@ * [ENHANCEMENT] Ingester: Add two metrics tracking resource utilization calculated by utilization based limiter: #5496 * `cortex_ingester_utilization_limiter_current_cpu_load`: The current exponential weighted moving average of the ingester's CPU load * `cortex_ingester_utilization_limiter_current_memory_usage_bytes`: The current ingester memory utilization +* [ENHANCEMENT] Distributor: add support for ingesting exponential histograms that are over the native histogram scale limit of 8 in OpenTelemetry format by downscaling them. #5532 * [BUGFIX] Ingester: Handle when previous ring state is leaving and the number of tokens has changed. #5204 * [BUGFIX] Querier: fix issue where queries that use the `timestamp()` function fail with `execution: attempted to read series at index 0 from stream, but the stream has already been exhausted` if streaming chunks from ingesters to queriers is enabled. #5370 * [BUGFIX] memberlist: bring back `memberlist_client_kv_store_count` metric that used to exist in Cortex, but got lost during dskit updates before Mimir 2.0. #5377 diff --git a/go.mod b/go.mod index ec77bef277a..af4846ceff3 100644 --- a/go.mod +++ b/go.mod @@ -64,7 +64,7 @@ require ( github.com/hashicorp/vault/api v1.9.2 github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 - github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheusremotewrite v0.81.0 + github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheusremotewrite v0.0.0-20230717235037-3f2821e2c1b1 github.com/prometheus/procfs v0.11.0 github.com/thanos-io/objstore v0.0.0-20230710163637-47c0118da0ca github.com/xlab/treeprint v1.2.0 diff --git a/go.sum b/go.sum index 76dee1444e3..7495185fb2f 100644 --- a/go.sum +++ b/go.sum @@ -1102,8 +1102,8 @@ github.com/open-telemetry/opentelemetry-collector-contrib/internal/common v0.81. github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.81.0 h1:sPjCHuqjn5UYDJOai4FulMCfLP+7AbspjHfv0jAtmD0= github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheus v0.81.0 h1:syUuhc/z2yIsTmL9jt2gmXkYUM/jgsQZoH6NAE6i54Q= github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheus v0.81.0/go.mod h1:LRzHoUpI8xZN5KXulEglZnbkYBHyiqHgQXGudIqpTtk= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheusremotewrite v0.81.0 h1:0Wzd9nh8WFfcY769RKfJU1qnEVSwy7g6+nfyyuFNCeE= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheusremotewrite v0.81.0/go.mod h1:4R9zh1OOvN7JGaN6qLK3uvH0ZO6vZdUeFx4TK+yK258= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheusremotewrite v0.0.0-20230717235037-3f2821e2c1b1 h1:+qLq78c38mU38gm1UCswt61NsM8O6NB0L2sFdLiwbbo= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheusremotewrite v0.0.0-20230717235037-3f2821e2c1b1/go.mod h1:FLUCs/7YJX0pauUBlj+5cy2h0ckjVMno2YyXsO/j89k= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= github.com/opentracing-contrib/go-grpc v0.0.0-20180928155321-4b5a12d3ff02/go.mod h1:JNdpVEzCpXBgIiv4ds+TzhN1hrtxq6ClLrTlT9OQRSc= diff --git a/vendor/github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheusremotewrite/histograms.go b/vendor/github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheusremotewrite/histograms.go index 293d318a3c5..ec25abcefcc 100644 --- a/vendor/github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheusremotewrite/histograms.go +++ b/vendor/github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheusremotewrite/histograms.go @@ -58,15 +58,20 @@ func addSingleExponentialHistogramDataPoint( // to Prometheus Native Histogram. func exponentialToNativeHistogram(p pmetric.ExponentialHistogramDataPoint) (prompb.Histogram, error) { scale := p.Scale() - if scale < -4 || scale > 8 { + if scale < -4 { return prompb.Histogram{}, fmt.Errorf("cannot convert exponential to native histogram."+ - " Scale must be <= 8 and >= -4, was %d", scale) - // TODO: downscale to 8 if scale > 8 + " Scale must be >= -4, was %d", scale) } - pSpans, pDeltas := convertBucketsLayout(p.Positive()) - nSpans, nDeltas := convertBucketsLayout(p.Negative()) + var scaleDown int32 + if scale > 8 { + scaleDown = scale - 8 + scale = 8 + } + + pSpans, pDeltas := convertBucketsLayout(p.Positive(), scaleDown) + nSpans, nDeltas := convertBucketsLayout(p.Negative(), scaleDown) h := prompb.Histogram{ Schema: scale, @@ -104,17 +109,19 @@ func exponentialToNativeHistogram(p pmetric.ExponentialHistogramDataPoint) (prom // The bucket indexes conversion was adjusted, since OTel exp. histogram bucket // index 0 corresponds to the range (1, base] while Prometheus bucket index 0 // to the range (base 1]. -func convertBucketsLayout(buckets pmetric.ExponentialHistogramDataPointBuckets) ([]prompb.BucketSpan, []int64) { +// +// scaleDown is the factor by which the buckets are scaled down. In other words 2^scaleDown buckets will be merged into one. +func convertBucketsLayout(buckets pmetric.ExponentialHistogramDataPointBuckets, scaleDown int32) ([]prompb.BucketSpan, []int64) { bucketCounts := buckets.BucketCounts() if bucketCounts.Len() == 0 { return nil, nil } var ( - spans []prompb.BucketSpan - deltas []int64 - prevCount int64 - nextBucketIdx int32 + spans []prompb.BucketSpan + deltas []int64 + count int64 + prevCount int64 ) appendDelta := func(count int64) { @@ -123,34 +130,67 @@ func convertBucketsLayout(buckets pmetric.ExponentialHistogramDataPointBuckets) prevCount = count } - for i := 0; i < bucketCounts.Len(); i++ { - count := int64(bucketCounts.At(i)) + // Let the compiler figure out that this is const during this function by + // moving it into a local variable. + numBuckets := bucketCounts.Len() + + // The offset is scaled and adjusted by 1 as described above. + bucketIdx := buckets.Offset()>>scaleDown + 1 + spans = append(spans, prompb.BucketSpan{ + Offset: bucketIdx, + Length: 0, + }) + + for i := 0; i < numBuckets; i++ { + // The offset is scaled and adjusted by 1 as described above. + nextBucketIdx := (int32(i)+buckets.Offset())>>scaleDown + 1 + if bucketIdx == nextBucketIdx { // We have not collected enough buckets to merge yet. + count += int64(bucketCounts.At(i)) + continue + } if count == 0 { + count = int64(bucketCounts.At(i)) continue } - // The offset is adjusted by 1 as described above. - bucketIdx := int32(i) + buckets.Offset() + 1 - delta := bucketIdx - nextBucketIdx - if i == 0 || delta > 2 { - // We have to create a new span, either because we are - // at the very beginning, or because we have found a gap + gap := nextBucketIdx - bucketIdx - 1 + if gap > 2 { + // We have to create a new span, because we have found a gap // of more than two buckets. The constant 2 is copied from the logic in // https://github.com/prometheus/client_golang/blob/27f0506d6ebbb117b6b697d0552ee5be2502c5f2/prometheus/histogram.go#L1296 spans = append(spans, prompb.BucketSpan{ - Offset: delta, + Offset: gap, Length: 0, }) } else { // We have found a small gap (or no gap at all). // Insert empty buckets as needed. - for j := int32(0); j < delta; j++ { + for j := int32(0); j < gap; j++ { appendDelta(0) } } appendDelta(count) - nextBucketIdx = bucketIdx + 1 + count = int64(bucketCounts.At(i)) + bucketIdx = nextBucketIdx + } + // Need to use the last item's index. The offset is scaled and adjusted by 1 as described above. + gap := (int32(numBuckets)+buckets.Offset()-1)>>scaleDown + 1 - bucketIdx + if gap > 2 { + // We have to create a new span, because we have found a gap + // of more than two buckets. The constant 2 is copied from the logic in + // https://github.com/prometheus/client_golang/blob/27f0506d6ebbb117b6b697d0552ee5be2502c5f2/prometheus/histogram.go#L1296 + spans = append(spans, prompb.BucketSpan{ + Offset: gap, + Length: 0, + }) + } else { + // We have found a small gap (or no gap at all). + // Insert empty buckets as needed. + for j := int32(0); j < gap; j++ { + appendDelta(0) + } } + appendDelta(count) return spans, deltas } diff --git a/vendor/modules.txt b/vendor/modules.txt index aeb8a3a5f15..80256d7b89a 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -776,7 +776,7 @@ github.com/oklog/ulid # github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheus v0.81.0 ## explicit; go 1.19 github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheus -# github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheusremotewrite v0.81.0 +# github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheusremotewrite v0.0.0-20230717235037-3f2821e2c1b1 ## explicit; go 1.19 github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheusremotewrite # github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e