@@ -95,7 +95,8 @@ type Distributor struct {
95
95
HATracker * ha.HATracker
96
96
97
97
// Per-user rate limiter.
98
- ingestionRateLimiter * limiter.RateLimiter
98
+ ingestionRateLimiter * limiter.RateLimiter
99
+ nativeHistogramIngestionRateLimiter * limiter.RateLimiter
99
100
100
101
// Manager for subservices (HA Tracker, distributor ring and client pool)
101
102
subservices * services.Manager
@@ -267,11 +268,13 @@ func New(cfg Config, clientConfig ingester_client.Config, limits *validation.Ove
267
268
// it's an internal dependency and can't join the distributors ring, we skip rate
268
269
// limiting.
269
270
var ingestionRateStrategy limiter.RateLimiterStrategy
271
+ var nativeHistogramIngestionRateStrategy limiter.RateLimiterStrategy
270
272
var distributorsLifeCycler * ring.Lifecycler
271
273
var distributorsRing * ring.Ring
272
274
273
275
if ! canJoinDistributorsRing {
274
276
ingestionRateStrategy = newInfiniteIngestionRateStrategy ()
277
+ nativeHistogramIngestionRateStrategy = newInfiniteIngestionRateStrategy ()
275
278
} else if limits .IngestionRateStrategy () == validation .GlobalIngestionRateStrategy {
276
279
distributorsLifeCycler , err = ring .NewLifecycler (cfg .DistributorRing .ToLifecyclerConfig (), nil , "distributor" , ringKey , true , true , log , prometheus .WrapRegistererWithPrefix ("cortex_" , reg ))
277
280
if err != nil {
@@ -285,21 +288,24 @@ func New(cfg Config, clientConfig ingester_client.Config, limits *validation.Ove
285
288
subservices = append (subservices , distributorsLifeCycler , distributorsRing )
286
289
287
290
ingestionRateStrategy = newGlobalIngestionRateStrategy (limits , distributorsLifeCycler )
291
+ nativeHistogramIngestionRateStrategy = newGlobalNativeHistogramIngestionRateStrategy (limits , distributorsLifeCycler )
288
292
} else {
289
293
ingestionRateStrategy = newLocalIngestionRateStrategy (limits )
294
+ nativeHistogramIngestionRateStrategy = newLocalNativeHistogramIngestionRateStrategy (limits )
290
295
}
291
296
292
297
d := & Distributor {
293
- cfg : cfg ,
294
- log : log ,
295
- ingestersRing : ingestersRing ,
296
- ingesterPool : NewPool (cfg .PoolConfig , ingestersRing , cfg .IngesterClientFactory , log ),
297
- distributorsLifeCycler : distributorsLifeCycler ,
298
- distributorsRing : distributorsRing ,
299
- limits : limits ,
300
- ingestionRateLimiter : limiter .NewRateLimiter (ingestionRateStrategy , 10 * time .Second ),
301
- HATracker : haTracker ,
302
- ingestionRate : util_math .NewEWMARate (0.2 , instanceIngestionRateTickInterval ),
298
+ cfg : cfg ,
299
+ log : log ,
300
+ ingestersRing : ingestersRing ,
301
+ ingesterPool : NewPool (cfg .PoolConfig , ingestersRing , cfg .IngesterClientFactory , log ),
302
+ distributorsLifeCycler : distributorsLifeCycler ,
303
+ distributorsRing : distributorsRing ,
304
+ limits : limits ,
305
+ ingestionRateLimiter : limiter .NewRateLimiter (ingestionRateStrategy , 10 * time .Second ),
306
+ nativeHistogramIngestionRateLimiter : limiter .NewRateLimiter (nativeHistogramIngestionRateStrategy , 10 * time .Second ),
307
+ HATracker : haTracker ,
308
+ ingestionRate : util_math .NewEWMARate (0.2 , instanceIngestionRateTickInterval ),
303
309
304
310
queryDuration : instrument .NewHistogramCollector (promauto .With (reg ).NewHistogramVec (prometheus.HistogramOpts {
305
311
Namespace : "cortex" ,
@@ -754,7 +760,7 @@ func (d *Distributor) Push(ctx context.Context, req *cortexpb.WriteRequest) (*co
754
760
}
755
761
756
762
// A WriteRequest can only contain series or metadata but not both. This might change in the future.
757
- seriesKeys , validatedTimeseries , validatedFloatSamples , validatedHistogramSamples , validatedExemplars , firstPartialErr , err := d .prepareSeriesKeys (ctx , req , userID , limits , removeReplica )
763
+ seriesKeys , nhSeriesKeys , validatedTimeseries , nhValidatedTimeseries , validatedFloatSamples , validatedHistogramSamples , validatedExemplars , firstPartialErr , err := d .prepareSeriesKeys (ctx , req , userID , limits , removeReplica )
758
764
if err != nil {
759
765
return nil , err
760
766
}
@@ -765,6 +771,15 @@ func (d *Distributor) Push(ctx context.Context, req *cortexpb.WriteRequest) (*co
765
771
d .receivedExemplars .WithLabelValues (userID ).Add (float64 (validatedExemplars ))
766
772
d .receivedMetadata .WithLabelValues (userID ).Add (float64 (len (validatedMetadata )))
767
773
774
+ if ! d .nativeHistogramIngestionRateLimiter .AllowN (now , userID , validatedHistogramSamples ) {
775
+ level .Warn (d .log ).Log ("msg" , "native histogram ingestion rate limit (%v) exceeded while adding %d native histogram samples" , d .nativeHistogramIngestionRateLimiter .Limit (now , userID ), validatedHistogramSamples )
776
+ d .validateMetrics .DiscardedSamples .WithLabelValues (validation .NativeHistogramRateLimited , userID ).Add (float64 (validatedHistogramSamples ))
777
+ validatedHistogramSamples = 0
778
+ } else {
779
+ seriesKeys = append (seriesKeys , nhSeriesKeys ... )
780
+ validatedTimeseries = append (validatedTimeseries , nhValidatedTimeseries ... )
781
+ }
782
+
768
783
if len (seriesKeys ) == 0 && len (metadataKeys ) == 0 {
769
784
// Ensure the request slice is reused if there's no series or metadata passing the validation.
770
785
cortexpb .ReuseSlice (req .Timeseries )
@@ -936,14 +951,16 @@ type samplesLabelSetEntry struct {
936
951
labels labels.Labels
937
952
}
938
953
939
- func (d * Distributor ) prepareSeriesKeys (ctx context.Context , req * cortexpb.WriteRequest , userID string , limits * validation.Limits , removeReplica bool ) ([]uint32 , []cortexpb.PreallocTimeseries , int , int , int , error , error ) {
954
+ func (d * Distributor ) prepareSeriesKeys (ctx context.Context , req * cortexpb.WriteRequest , userID string , limits * validation.Limits , removeReplica bool ) ([]uint32 , []uint32 , []cortexpb. PreallocTimeseries , [] cortexpb.PreallocTimeseries , int , int , int , error , error ) {
940
955
pSpan , _ := opentracing .StartSpanFromContext (ctx , "prepareSeriesKeys" )
941
956
defer pSpan .Finish ()
942
957
943
958
// For each timeseries or samples, we compute a hash to distribute across ingesters;
944
- // check each sample/metadata and discard if outside limits.
959
+ // check each sample/metadata and discard if outside limits.
945
960
validatedTimeseries := make ([]cortexpb.PreallocTimeseries , 0 , len (req .Timeseries ))
961
+ nhValidatedTimeseries := make ([]cortexpb.PreallocTimeseries , 0 , len (req .Timeseries ))
946
962
seriesKeys := make ([]uint32 , 0 , len (req .Timeseries ))
963
+ nhSeriesKeys := make ([]uint32 , 0 , len (req .Timeseries ))
947
964
validatedFloatSamples := 0
948
965
validatedHistogramSamples := 0
949
966
validatedExemplars := 0
@@ -1051,7 +1068,7 @@ func (d *Distributor) prepareSeriesKeys(ctx context.Context, req *cortexpb.Write
1051
1068
// label and dropped labels (if any)
1052
1069
key , err := d .tokenForLabels (userID , ts .Labels )
1053
1070
if err != nil {
1054
- return nil , nil , 0 , 0 , 0 , nil , err
1071
+ return nil , nil , nil , nil , 0 , 0 , 0 , nil , err
1055
1072
}
1056
1073
validatedSeries , validationErr := d .validateSeries (ts , userID , skipLabelNameValidation , limits )
1057
1074
@@ -1086,8 +1103,13 @@ func (d *Distributor) prepareSeriesKeys(ctx context.Context, req *cortexpb.Write
1086
1103
}
1087
1104
}
1088
1105
1089
- seriesKeys = append (seriesKeys , key )
1090
- validatedTimeseries = append (validatedTimeseries , validatedSeries )
1106
+ if len (ts .Histograms ) > 0 {
1107
+ nhSeriesKeys = append (nhSeriesKeys , key )
1108
+ nhValidatedTimeseries = append (nhValidatedTimeseries , validatedSeries )
1109
+ } else {
1110
+ seriesKeys = append (seriesKeys , key )
1111
+ validatedTimeseries = append (validatedTimeseries , validatedSeries )
1112
+ }
1091
1113
validatedFloatSamples += len (ts .Samples )
1092
1114
validatedHistogramSamples += len (ts .Histograms )
1093
1115
validatedExemplars += len (ts .Exemplars )
@@ -1103,7 +1125,7 @@ func (d *Distributor) prepareSeriesKeys(ctx context.Context, req *cortexpb.Write
1103
1125
}
1104
1126
}
1105
1127
1106
- return seriesKeys , validatedTimeseries , validatedFloatSamples , validatedHistogramSamples , validatedExemplars , firstPartialErr , nil
1128
+ return seriesKeys , nhSeriesKeys , validatedTimeseries , nhValidatedTimeseries , validatedFloatSamples , validatedHistogramSamples , validatedExemplars , firstPartialErr , nil
1107
1129
}
1108
1130
1109
1131
func sortLabelsIfNeeded (labels []cortexpb.LabelAdapter ) {
0 commit comments