@@ -366,22 +366,117 @@ func TestIngesterPerLabelsetLimitExceeded(t *testing.T) {
366
366
cortex_ingester_usage_per_labelset{labelset="{comp2=\"compValue2\"}",limit="max_series",user="1"} 3
367
367
` ), "cortex_ingester_usage_per_labelset" , "cortex_ingester_limits_per_labelset" ))
368
368
369
- // Should remove metrics when the limits is removed
369
+ // Add default partition -> no label set configured working as a fallback when a series
370
+ // doesn't match any existing label set limit.
371
+ emptyLabels := labels .EmptyLabels ()
372
+ defaultPartitionLimits := validation.LimitsPerLabelSet {LabelSet : emptyLabels ,
373
+ Limits : validation.LimitsPerLabelSetEntry {
374
+ MaxSeries : 2 ,
375
+ },
376
+ }
377
+ limits .LimitsPerLabelSet = append (limits .LimitsPerLabelSet , defaultPartitionLimits )
378
+ b , err = json .Marshal (limits )
379
+ require .NoError (t , err )
380
+ require .NoError (t , limits .UnmarshalJSON (b ))
381
+ tenantLimits .setLimits (userID , & limits )
382
+
383
+ lbls = []string {labels .MetricName , "test_default" }
384
+ for i := 0 ; i < 2 ; i ++ {
385
+ _ , err = ing .Push (ctx , cortexpb .ToWriteRequest (
386
+ []labels.Labels {labels .FromStrings (append (lbls , "series" , strconv .Itoa (i ))... )}, samples , nil , nil , cortexpb .API ))
387
+ require .NoError (t , err )
388
+ }
389
+
390
+ // Max series limit for default partition is 2 so 1 more series will be throttled.
391
+ _ , err = ing .Push (ctx , cortexpb .ToWriteRequest (
392
+ []labels.Labels {labels .FromStrings (append (lbls , "extraLabel" , "extraValueUpdate2" )... )}, samples , nil , nil , cortexpb .API ))
393
+ httpResp , ok = httpgrpc .HTTPResponseFromError (err )
394
+ require .True (t , ok , "returned error is not an httpgrpc response" )
395
+ assert .Equal (t , http .StatusBadRequest , int (httpResp .Code ))
396
+ require .ErrorContains (t , err , emptyLabels .String ())
397
+
398
+ ing .updateActiveSeries (ctx )
399
+ require .NoError (t , testutil .GatherAndCompare (registry , bytes .NewBufferString (`
400
+ # HELP cortex_ingester_limits_per_labelset Limits per user and labelset.
401
+ # TYPE cortex_ingester_limits_per_labelset gauge
402
+ cortex_ingester_limits_per_labelset{labelset="{__name__=\"metric_name\", comp2=\"compValue2\"}",limit="max_series",user="1"} 3
403
+ cortex_ingester_limits_per_labelset{labelset="{comp1=\"compValue1\", comp2=\"compValue2\"}",limit="max_series",user="1"} 2
404
+ cortex_ingester_limits_per_labelset{labelset="{comp1=\"compValue1\"}",limit="max_series",user="1"} 10
405
+ cortex_ingester_limits_per_labelset{labelset="{comp2=\"compValue2\"}",limit="max_series",user="1"} 10
406
+ cortex_ingester_limits_per_labelset{labelset="{label1=\"value1\"}",limit="max_series",user="1"} 3
407
+ cortex_ingester_limits_per_labelset{labelset="{label2=\"value2\"}",limit="max_series",user="1"} 2
408
+ cortex_ingester_limits_per_labelset{labelset="{}",limit="max_series",user="1"} 2
409
+ # HELP cortex_ingester_usage_per_labelset Current usage per user and labelset.
410
+ # TYPE cortex_ingester_usage_per_labelset gauge
411
+ cortex_ingester_usage_per_labelset{labelset="{__name__=\"metric_name\", comp2=\"compValue2\"}",limit="max_series",user="1"} 3
412
+ cortex_ingester_usage_per_labelset{labelset="{label1=\"value1\"}",limit="max_series",user="1"} 3
413
+ cortex_ingester_usage_per_labelset{labelset="{label2=\"value2\"}",limit="max_series",user="1"} 2
414
+ cortex_ingester_usage_per_labelset{labelset="{comp1=\"compValue1\", comp2=\"compValue2\"}",limit="max_series",user="1"} 2
415
+ cortex_ingester_usage_per_labelset{labelset="{comp1=\"compValue1\"}",limit="max_series",user="1"} 7
416
+ cortex_ingester_usage_per_labelset{labelset="{comp2=\"compValue2\"}",limit="max_series",user="1"} 3
417
+ cortex_ingester_usage_per_labelset{labelset="{}",limit="max_series",user="1"} 2
418
+ ` ), "cortex_ingester_usage_per_labelset" , "cortex_ingester_limits_per_labelset" ))
419
+
420
+ // Add a new label set limit.
421
+ limits .LimitsPerLabelSet = append (limits .LimitsPerLabelSet ,
422
+ validation.LimitsPerLabelSet {LabelSet : labels .FromMap (map [string ]string {
423
+ "series" : "0" ,
424
+ }),
425
+ Limits : validation.LimitsPerLabelSetEntry {
426
+ MaxSeries : 3 ,
427
+ },
428
+ },
429
+ )
430
+ b , err = json .Marshal (limits )
431
+ require .NoError (t , err )
432
+ require .NoError (t , limits .UnmarshalJSON (b ))
433
+ tenantLimits .setLimits (userID , & limits )
434
+ ing .updateActiveSeries (ctx )
435
+ // Default partition usage reduced from 2 to 1 as one series in default partition
436
+ // now counted into the new partition.
437
+ require .NoError (t , testutil .GatherAndCompare (registry , bytes .NewBufferString (`
438
+ # HELP cortex_ingester_limits_per_labelset Limits per user and labelset.
439
+ # TYPE cortex_ingester_limits_per_labelset gauge
440
+ cortex_ingester_limits_per_labelset{labelset="{__name__=\"metric_name\", comp2=\"compValue2\"}",limit="max_series",user="1"} 3
441
+ cortex_ingester_limits_per_labelset{labelset="{comp1=\"compValue1\", comp2=\"compValue2\"}",limit="max_series",user="1"} 2
442
+ cortex_ingester_limits_per_labelset{labelset="{comp1=\"compValue1\"}",limit="max_series",user="1"} 10
443
+ cortex_ingester_limits_per_labelset{labelset="{comp2=\"compValue2\"}",limit="max_series",user="1"} 10
444
+ cortex_ingester_limits_per_labelset{labelset="{label1=\"value1\"}",limit="max_series",user="1"} 3
445
+ cortex_ingester_limits_per_labelset{labelset="{label2=\"value2\"}",limit="max_series",user="1"} 2
446
+ cortex_ingester_limits_per_labelset{labelset="{series=\"0\"}",limit="max_series",user="1"} 3
447
+ cortex_ingester_limits_per_labelset{labelset="{}",limit="max_series",user="1"} 2
448
+ # HELP cortex_ingester_usage_per_labelset Current usage per user and labelset.
449
+ # TYPE cortex_ingester_usage_per_labelset gauge
450
+ cortex_ingester_usage_per_labelset{labelset="{__name__=\"metric_name\", comp2=\"compValue2\"}",limit="max_series",user="1"} 3
451
+ cortex_ingester_usage_per_labelset{labelset="{label1=\"value1\"}",limit="max_series",user="1"} 3
452
+ cortex_ingester_usage_per_labelset{labelset="{label2=\"value2\"}",limit="max_series",user="1"} 2
453
+ cortex_ingester_usage_per_labelset{labelset="{comp1=\"compValue1\", comp2=\"compValue2\"}",limit="max_series",user="1"} 2
454
+ cortex_ingester_usage_per_labelset{labelset="{comp1=\"compValue1\"}",limit="max_series",user="1"} 7
455
+ cortex_ingester_usage_per_labelset{labelset="{comp2=\"compValue2\"}",limit="max_series",user="1"} 3
456
+ cortex_ingester_usage_per_labelset{labelset="{series=\"0\"}",limit="max_series",user="1"} 1
457
+ cortex_ingester_usage_per_labelset{labelset="{}",limit="max_series",user="1"} 1
458
+ ` ), "cortex_ingester_usage_per_labelset" , "cortex_ingester_limits_per_labelset" ))
459
+
460
+ // Should remove metrics when the limits is removed, keep default partition limit
370
461
limits .LimitsPerLabelSet = limits .LimitsPerLabelSet [:2 ]
462
+ limits .LimitsPerLabelSet = append (limits .LimitsPerLabelSet , defaultPartitionLimits )
371
463
b , err = json .Marshal (limits )
372
464
require .NoError (t , err )
373
465
require .NoError (t , limits .UnmarshalJSON (b ))
374
466
tenantLimits .setLimits (userID , & limits )
375
467
ing .updateActiveSeries (ctx )
468
+ // Default partition usage increased from 2 to 10 as some existing partitions got removed.
376
469
require .NoError (t , testutil .GatherAndCompare (registry , bytes .NewBufferString (`
377
470
# HELP cortex_ingester_limits_per_labelset Limits per user and labelset.
378
471
# TYPE cortex_ingester_limits_per_labelset gauge
379
472
cortex_ingester_limits_per_labelset{labelset="{label1=\"value1\"}",limit="max_series",user="1"} 3
380
473
cortex_ingester_limits_per_labelset{labelset="{label2=\"value2\"}",limit="max_series",user="1"} 2
474
+ cortex_ingester_limits_per_labelset{labelset="{}",limit="max_series",user="1"} 2
381
475
# HELP cortex_ingester_usage_per_labelset Current usage per user and labelset.
382
476
# TYPE cortex_ingester_usage_per_labelset gauge
383
477
cortex_ingester_usage_per_labelset{labelset="{label1=\"value1\"}",limit="max_series",user="1"} 3
384
478
cortex_ingester_usage_per_labelset{labelset="{label2=\"value2\"}",limit="max_series",user="1"} 2
479
+ cortex_ingester_usage_per_labelset{labelset="{}",limit="max_series",user="1"} 10
385
480
` ), "cortex_ingester_usage_per_labelset" , "cortex_ingester_limits_per_labelset" ))
386
481
387
482
// Should persist between restarts
@@ -396,10 +491,12 @@ func TestIngesterPerLabelsetLimitExceeded(t *testing.T) {
396
491
# TYPE cortex_ingester_limits_per_labelset gauge
397
492
cortex_ingester_limits_per_labelset{labelset="{label1=\"value1\"}",limit="max_series",user="1"} 3
398
493
cortex_ingester_limits_per_labelset{labelset="{label2=\"value2\"}",limit="max_series",user="1"} 2
494
+ cortex_ingester_limits_per_labelset{labelset="{}",limit="max_series",user="1"} 2
399
495
# HELP cortex_ingester_usage_per_labelset Current usage per user and labelset.
400
496
# TYPE cortex_ingester_usage_per_labelset gauge
401
497
cortex_ingester_usage_per_labelset{labelset="{label1=\"value1\"}",limit="max_series",user="1"} 3
402
498
cortex_ingester_usage_per_labelset{labelset="{label2=\"value2\"}",limit="max_series",user="1"} 2
499
+ cortex_ingester_usage_per_labelset{labelset="{}",limit="max_series",user="1"} 10
403
500
` ), "cortex_ingester_usage_per_labelset" , "cortex_ingester_limits_per_labelset" ))
404
501
services .StopAndAwaitTerminated (context .Background (), ing ) //nolint:errcheck
405
502
@@ -420,6 +517,13 @@ func TestPushRace(t *testing.T) {
420
517
MaxSeries : 10e10 ,
421
518
},
422
519
},
520
+ {
521
+ // Default partition.
522
+ LabelSet : labels .EmptyLabels (),
523
+ Limits : validation.LimitsPerLabelSetEntry {
524
+ MaxSeries : 10e10 ,
525
+ },
526
+ },
423
527
}
424
528
425
529
dir := t .TempDir ()
@@ -451,6 +555,10 @@ func TestPushRace(t *testing.T) {
451
555
defer wg .Done ()
452
556
_ , err := ing .Push (ctx , cortexpb .ToWriteRequest ([]labels.Labels {labels .FromStrings (labels .MetricName , "foo" , "userId" , userID , "k" , strconv .Itoa (k ))}, []cortexpb.Sample {sample1 }, nil , nil , cortexpb .API ))
453
557
require .NoError (t , err )
558
+
559
+ // Go to default partition.
560
+ _ , err = ing .Push (ctx , cortexpb .ToWriteRequest ([]labels.Labels {labels .FromStrings (labels .MetricName , "bar" , "userId" , userID , "k" , strconv .Itoa (k ))}, []cortexpb.Sample {sample1 }, nil , nil , cortexpb .API ))
561
+ require .NoError (t , err )
454
562
}()
455
563
}
456
564
}
@@ -472,13 +580,13 @@ func TestPushRace(t *testing.T) {
472
580
err = ir .Series (p .At (), & builder , nil )
473
581
require .NoError (t , err )
474
582
lbls := builder .Labels ()
475
- require .Equal (t , "foo" , lbls .Get (labels .MetricName ))
583
+ require .True (t , lbls . Get ( labels . MetricName ) == "foo" || lbls .Get (labels .MetricName ) == "bar" )
476
584
require .Equal (t , "1" , lbls .Get ("userId" ))
477
585
require .NotEmpty (t , lbls .Get ("k" ))
478
586
builder .Reset ()
479
587
}
480
- require .Equal (t , numberOfSeries , total )
481
- require .Equal (t , uint64 (numberOfSeries ), db .Head ().NumSeries ())
588
+ require .Equal (t , 2 * numberOfSeries , total )
589
+ require .Equal (t , uint64 (2 * numberOfSeries ), db .Head ().NumSeries ())
482
590
}
483
591
484
592
func TestIngesterUserLimitExceeded (t * testing.T ) {
0 commit comments