Skip to content

Commit 87779d2

Browse files
committed
Use prometheus NH validate
Signed-off-by: SungJin1212 <[email protected]>
1 parent 2602c78 commit 87779d2

File tree

4 files changed

+118
-135
lines changed

4 files changed

+118
-135
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
* [ENHANCEMENT] Ingester: Add `enable_matcher_optimization` config to apply low selectivity matchers lazily. #7063
66
* [ENHANCEMENT] Distributor: Add a label references validation for remote write v2 request. #7074
7-
* [ENHANCEMENT] Distributor: Add count validations for native histogram. #7072
7+
* [ENHANCEMENT] Distributor: Add count, spans, and buckets validations for native histogram. #7072
88
* [BUGFIX] Compactor: Avoid race condition which allow a grouper to not compact all partitions. #7082
99

1010
## 1.20.0 in progress

pkg/util/validation/errors.go

Lines changed: 9 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -282,60 +282,20 @@ func (e *nativeHistogramSampleSizeBytesExceededError) Error() string {
282282
return fmt.Sprintf("native histogram sample size bytes exceeded for metric (actual: %d, limit: %d) metric: %.200q", e.nhSampleSizeBytes, e.limit, formatLabelSet(e.series))
283283
}
284284

285-
// nativeHistogramMisMatchCountError is a ValidationError implementation for native histogram
286-
// where the Count does not match the sum of observations in the buckets.
287-
type nativeHistogramMisMatchCountError struct {
288-
series []cortexpb.LabelAdapter
289-
observations uint64
290-
count uint64
291-
}
292-
293-
func newNativeHistogramMisMatchedCountError(series []cortexpb.LabelAdapter, observations, count uint64) ValidationError {
294-
return &nativeHistogramMisMatchCountError{
295-
series: series,
296-
observations: observations,
297-
count: count,
298-
}
299-
}
300-
301-
func (e *nativeHistogramMisMatchCountError) Error() string {
302-
return fmt.Sprintf("native histogram bucket count mismatch: count is %d, but observations found in buckets is %d, metric: %.200q", e.count, e.observations, formatLabelSet(e.series))
303-
}
304-
305-
// nativeHistogramNegativeCountError is a ValidationError implementation for float native histogram
306-
// where the Count field is negative.
307-
type nativeHistogramNegativeCountError struct {
308-
series []cortexpb.LabelAdapter
309-
count float64
310-
}
311-
312-
func newNativeHistogramNegativeCountError(series []cortexpb.LabelAdapter, count float64) ValidationError {
313-
return &nativeHistogramNegativeCountError{
314-
series: series,
315-
count: count,
316-
}
317-
}
318-
319-
func (e *nativeHistogramNegativeCountError) Error() string {
320-
return fmt.Sprintf("native histogram observation count %.2f is negative, metric: %.200q", e.count, formatLabelSet(e.series))
321-
}
322-
323-
// nativeHistogramNegativeBucketCountError is a ValidationError implementation for float native histogram
324-
// where the count in buckets is negative.
325-
type nativeHistogramNegativeBucketCountError struct {
326-
series []cortexpb.LabelAdapter
327-
count float64
285+
type nativeHistogramInvalidError struct {
286+
nhValidationErr error
287+
series []cortexpb.LabelAdapter
328288
}
329289

330-
func newNativeHistogramNegativeBucketCountError(series []cortexpb.LabelAdapter, count float64) ValidationError {
331-
return &nativeHistogramNegativeBucketCountError{
332-
series: series,
333-
count: count,
290+
func newNativeHistogramInvalidError(series []cortexpb.LabelAdapter, nhValidationErr error) ValidationError {
291+
return &nativeHistogramInvalidError{
292+
series: series,
293+
nhValidationErr: nhValidationErr,
334294
}
335295
}
336296

337-
func (e *nativeHistogramNegativeBucketCountError) Error() string {
338-
return fmt.Sprintf("native histogram buckets have a negative count: %.2f, metric: %.200q", e.count, formatLabelSet(e.series))
297+
func (e *nativeHistogramInvalidError) Error() string {
298+
return fmt.Sprintf("invalid native histogram, validation err: %v, metric: %.200q", e.nhValidationErr, formatLabelSet(e.series))
339299
}
340300

341301
// formatLabelSet formats label adapters as a metric name with labels, while preserving

pkg/util/validation/validate.go

Lines changed: 24 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package validation
33
import (
44
"errors"
55
"fmt"
6-
"math"
76
"net/http"
87
"strings"
98
"time"
@@ -62,9 +61,7 @@ const (
6261
nativeHistogramBucketCountLimitExceeded = "native_histogram_buckets_exceeded"
6362
nativeHistogramInvalidSchema = "native_histogram_invalid_schema"
6463
nativeHistogramSampleSizeBytesExceeded = "native_histogram_sample_size_bytes_exceeded"
65-
nativeHistogramNegativeCount = "native_histogram_negative_count"
66-
nativeHistogramNegativeBucketCount = "native_histogram_negative_bucket_count"
67-
nativeHistogramMisMatchCount = "native_histogram_mismatch_count"
64+
nativeHistogramInvalid = "native_histogram_invalid"
6865

6966
// RateLimited is one of the values for the reason to discard samples.
7067
// Declared here to avoid duplication in ingester and distributor.
@@ -385,77 +382,33 @@ func ValidateNativeHistogram(validateMetrics *ValidateMetrics, limits *Limits, u
385382
return cortexpb.Histogram{}, newNativeHistogramSchemaInvalidError(ls, int(histogramSample.Schema))
386383
}
387384

388-
var nCount, pCount uint64
389-
if histogramSample.IsFloatHistogram() {
390-
if c, err := checkHistogramBuckets(histogramSample.GetNegativeCounts(), &nCount, false); err != nil {
391-
validateMetrics.DiscardedSamples.WithLabelValues(nativeHistogramNegativeBucketCount, userID).Inc()
392-
return cortexpb.Histogram{}, newNativeHistogramNegativeBucketCountError(ls, c)
393-
}
394-
395-
if c, err := checkHistogramBuckets(histogramSample.GetPositiveCounts(), &pCount, false); err != nil {
396-
validateMetrics.DiscardedSamples.WithLabelValues(nativeHistogramNegativeBucketCount, userID).Inc()
397-
return cortexpb.Histogram{}, newNativeHistogramNegativeBucketCountError(ls, c)
398-
}
399-
400-
if histogramSample.GetZeroCountFloat() < 0 {
401-
validateMetrics.DiscardedSamples.WithLabelValues(nativeHistogramNegativeBucketCount, userID).Inc()
402-
return cortexpb.Histogram{}, newNativeHistogramNegativeBucketCountError(ls, histogramSample.GetZeroCountFloat())
403-
}
404-
405-
if histogramSample.GetCountFloat() < 0 {
406-
// validate if float histogram has negative count
407-
validateMetrics.DiscardedSamples.WithLabelValues(nativeHistogramNegativeCount, userID).Inc()
408-
return cortexpb.Histogram{}, newNativeHistogramNegativeCountError(ls, histogramSample.GetCountFloat())
409-
}
410-
} else {
411-
if c, err := checkHistogramBuckets(histogramSample.GetNegativeDeltas(), &nCount, true); err != nil {
412-
validateMetrics.DiscardedSamples.WithLabelValues(nativeHistogramNegativeBucketCount, userID).Inc()
413-
return cortexpb.Histogram{}, newNativeHistogramNegativeBucketCountError(ls, c)
414-
}
415-
416-
if c, err := checkHistogramBuckets(histogramSample.GetPositiveDeltas(), &pCount, true); err != nil {
417-
validateMetrics.DiscardedSamples.WithLabelValues(nativeHistogramNegativeBucketCount, userID).Inc()
418-
return cortexpb.Histogram{}, newNativeHistogramNegativeBucketCountError(ls, c)
419-
}
420-
421-
// validate if there is mismatch between count with observations in buckets
422-
observations := nCount + pCount + histogramSample.GetZeroCountInt()
423-
count := histogramSample.GetCountInt()
424-
425-
if math.IsNaN(histogramSample.Sum) {
426-
if observations > count {
427-
validateMetrics.DiscardedSamples.WithLabelValues(nativeHistogramMisMatchCount, userID).Inc()
428-
return cortexpb.Histogram{}, newNativeHistogramMisMatchedCountError(ls, observations, count)
429-
}
430-
} else {
431-
if observations != count {
432-
validateMetrics.DiscardedSamples.WithLabelValues(nativeHistogramMisMatchCount, userID).Inc()
433-
return cortexpb.Histogram{}, newNativeHistogramMisMatchedCountError(ls, observations, count)
434-
}
435-
}
436-
}
437-
438-
if limits.MaxNativeHistogramBuckets == 0 {
439-
return histogramSample, nil
440-
}
441-
442385
var (
443386
exceedLimit bool
444387
)
445388

446389
if histogramSample.IsFloatHistogram() {
447-
// Initial check to see if the bucket limit is exceeded or not. If not, we can avoid type casting.
390+
fh := cortexpb.FloatHistogramProtoToFloatHistogram(histogramSample)
391+
if err := fh.Validate(); err != nil {
392+
validateMetrics.DiscardedSamples.WithLabelValues(nativeHistogramInvalid, userID).Inc()
393+
return cortexpb.Histogram{}, newNativeHistogramInvalidError(ls, err)
394+
}
395+
396+
// limit check
397+
if limits.MaxNativeHistogramBuckets == 0 {
398+
return histogramSample, nil
399+
}
400+
448401
exceedLimit = len(histogramSample.PositiveCounts)+len(histogramSample.NegativeCounts) > limits.MaxNativeHistogramBuckets
449402
if !exceedLimit {
450403
return histogramSample, nil
451404
}
405+
452406
// Exceed limit.
453407
if histogramSample.Schema <= histogram.ExponentialSchemaMin {
454408
validateMetrics.DiscardedSamples.WithLabelValues(nativeHistogramBucketCountLimitExceeded, userID).Inc()
455409
return cortexpb.Histogram{}, newHistogramBucketLimitExceededError(ls, limits.MaxNativeHistogramBuckets)
456410
}
457411

458-
fh := cortexpb.FloatHistogramProtoToFloatHistogram(histogramSample)
459412
oBuckets := len(fh.PositiveBuckets) + len(fh.NegativeBuckets)
460413
for len(fh.PositiveBuckets)+len(fh.NegativeBuckets) > limits.MaxNativeHistogramBuckets {
461414
if fh.Schema <= histogram.ExponentialSchemaMin {
@@ -471,7 +424,17 @@ func ValidateNativeHistogram(validateMetrics *ValidateMetrics, limits *Limits, u
471424
return cortexpb.FloatHistogramToHistogramProto(histogramSample.TimestampMs, fh), nil
472425
}
473426

474-
// Initial check to see if bucket limit is exceeded or not. If not, we can avoid type casting.
427+
h := cortexpb.HistogramProtoToHistogram(histogramSample)
428+
if err := h.Validate(); err != nil {
429+
validateMetrics.DiscardedSamples.WithLabelValues(nativeHistogramInvalid, userID).Inc()
430+
return cortexpb.Histogram{}, newNativeHistogramInvalidError(ls, err)
431+
}
432+
433+
// limit check
434+
if limits.MaxNativeHistogramBuckets == 0 {
435+
return histogramSample, nil
436+
}
437+
475438
exceedLimit = len(histogramSample.PositiveDeltas)+len(histogramSample.NegativeDeltas) > limits.MaxNativeHistogramBuckets
476439
if !exceedLimit {
477440
return histogramSample, nil
@@ -481,7 +444,6 @@ func ValidateNativeHistogram(validateMetrics *ValidateMetrics, limits *Limits, u
481444
validateMetrics.DiscardedSamples.WithLabelValues(nativeHistogramBucketCountLimitExceeded, userID).Inc()
482445
return cortexpb.Histogram{}, newHistogramBucketLimitExceededError(ls, limits.MaxNativeHistogramBuckets)
483446
}
484-
h := cortexpb.HistogramProtoToHistogram(histogramSample)
485447
oBuckets := len(h.PositiveBuckets) + len(h.NegativeBuckets)
486448
for len(h.PositiveBuckets)+len(h.NegativeBuckets) > limits.MaxNativeHistogramBuckets {
487449
if h.Schema <= histogram.ExponentialSchemaMin {

0 commit comments

Comments
 (0)