@@ -3,7 +3,6 @@ package validation
33import (
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