Skip to content

Commit c99bfe5

Browse files
authored
fix distributor sampling rule processing priority (#4491)
1 parent 690a4f6 commit c99bfe5

File tree

2 files changed

+51
-34
lines changed

2 files changed

+51
-34
lines changed

pkg/distributor/distributor.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ func (l lazyUsageGroups) String() string {
347347
groups := l()
348348
result := make([]string, len(groups))
349349
for pos := range groups {
350-
result[pos] = groups[pos].ResolvedName
350+
result[pos] = groups[pos].String()
351351
}
352352
return fmt.Sprintf("%v", result)
353353
}
@@ -1021,9 +1021,9 @@ func (d *Distributor) shouldSample(tenantID string, groupsInRequest []validation
10211021
samplingProbability := 1.0
10221022
var match *validation.UsageGroupMatchName
10231023
for _, group := range groupsInRequest {
1024-
probabilityCfg, found := l.UsageGroups[group.ConfiguredName]
1024+
probabilityCfg, found := l.UsageGroups[group.ResolvedName]
10251025
if !found {
1026-
probabilityCfg, found = l.UsageGroups[group.ResolvedName]
1026+
probabilityCfg, found = l.UsageGroups[group.ConfiguredName]
10271027
}
10281028
if !found {
10291029
continue

pkg/distributor/distributor_test.go

Lines changed: 48 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2342,22 +2342,19 @@ func TestPush_LabelRewrites(t *testing.T) {
23422342
func TestDistributor_shouldSample(t *testing.T) {
23432343
tests := []struct {
23442344
name string
2345-
tenantID string
23462345
groups []validation.UsageGroupMatchName
23472346
samplingConfig *sampling.Config
23482347
expected bool
23492348
expectedMatch *sampling.Source
23502349
}{
23512350
{
23522351
name: "no sampling config - should accept",
2353-
tenantID: "test-tenant",
23542352
groups: []validation.UsageGroupMatchName{},
23552353
expected: true,
23562354
},
23572355
{
2358-
name: "no matching groups - should accept",
2359-
tenantID: "test-tenant",
2360-
groups: []validation.UsageGroupMatchName{{ConfiguredName: "group1", ResolvedName: "group1"}},
2356+
name: "no matching groups - should accept",
2357+
groups: []validation.UsageGroupMatchName{{ConfiguredName: "group1", ResolvedName: "group1"}},
23612358
samplingConfig: &sampling.Config{
23622359
UsageGroups: map[string]sampling.UsageGroupSampling{
23632360
"group2": {Probability: 0.5},
@@ -2366,9 +2363,8 @@ func TestDistributor_shouldSample(t *testing.T) {
23662363
expected: true,
23672364
},
23682365
{
2369-
name: "matching group with 1.0 probability - should accept",
2370-
tenantID: "test-tenant",
2371-
groups: []validation.UsageGroupMatchName{{ConfiguredName: "group1", ResolvedName: "group1"}},
2366+
name: "matching group with 1.0 probability - should accept",
2367+
groups: []validation.UsageGroupMatchName{{ConfiguredName: "group1", ResolvedName: "group1"}},
23722368
samplingConfig: &sampling.Config{
23732369
UsageGroups: map[string]sampling.UsageGroupSampling{
23742370
"group1": {Probability: 1.0},
@@ -2381,9 +2377,8 @@ func TestDistributor_shouldSample(t *testing.T) {
23812377
},
23822378
},
23832379
{
2384-
name: "matching group with dynamic name - should accept",
2385-
tenantID: "test-tenant",
2386-
groups: []validation.UsageGroupMatchName{{ConfiguredName: "configured-name", ResolvedName: "resolved-name"}},
2380+
name: "matching group with dynamic name - should accept",
2381+
groups: []validation.UsageGroupMatchName{{ConfiguredName: "configured-name", ResolvedName: "resolved-name"}},
23872382
samplingConfig: &sampling.Config{
23882383
UsageGroups: map[string]sampling.UsageGroupSampling{
23892384
"configured-name": {Probability: 1.0},
@@ -2396,9 +2391,8 @@ func TestDistributor_shouldSample(t *testing.T) {
23962391
},
23972392
},
23982393
{
2399-
name: "matching group with 0.0 probability - should reject",
2400-
tenantID: "test-tenant",
2401-
groups: []validation.UsageGroupMatchName{{ConfiguredName: "group1", ResolvedName: "group1"}},
2394+
name: "matching group with 0.0 probability - should reject",
2395+
groups: []validation.UsageGroupMatchName{{ConfiguredName: "group1", ResolvedName: "group1"}},
24022396
samplingConfig: &sampling.Config{
24032397
UsageGroups: map[string]sampling.UsageGroupSampling{
24042398
"group1": {Probability: 0.0},
@@ -2411,8 +2405,7 @@ func TestDistributor_shouldSample(t *testing.T) {
24112405
},
24122406
},
24132407
{
2414-
name: "multiple matching groups - should use minimum probability",
2415-
tenantID: "test-tenant",
2408+
name: "multiple matching groups - should use minimum probability",
24162409
groups: []validation.UsageGroupMatchName{
24172410
{ConfiguredName: "group1", ResolvedName: "group1"},
24182411
{ConfiguredName: "group2", ResolvedName: "group2"},
@@ -2430,41 +2423,56 @@ func TestDistributor_shouldSample(t *testing.T) {
24302423
},
24312424
},
24322425
{
2433-
name: "multiple matching groups - should prioritize specific group",
2434-
tenantID: "test-tenant",
2426+
name: "multiple matching groups - should prioritize specific group",
24352427
groups: []validation.UsageGroupMatchName{
24362428
{ConfiguredName: "${labels.service_name}", ResolvedName: "test_service"},
24372429
{ConfiguredName: "test_service", ResolvedName: "test_service"},
24382430
},
24392431
samplingConfig: &sampling.Config{
24402432
UsageGroups: map[string]sampling.UsageGroupSampling{
24412433
"${labels.service_name}": {Probability: 1.0},
2442-
"test_service": {Probability: 1.0},
2434+
"test_service": {Probability: 0.0},
24432435
},
24442436
},
2445-
expected: true,
2437+
expected: false,
24462438
expectedMatch: &sampling.Source{
24472439
UsageGroup: "test_service",
2448-
Probability: 1.0,
2440+
Probability: 0.0,
24492441
},
24502442
},
24512443
{
2452-
name: "multiple matching groups - should prioritize specific group (reversed order)",
2453-
tenantID: "test-tenant",
2444+
name: "multiple matching groups - should prioritize specific group (reversed order)",
24542445
groups: []validation.UsageGroupMatchName{
24552446
{ConfiguredName: "test_service", ResolvedName: "test_service"},
24562447
{ConfiguredName: "${labels.service_name}", ResolvedName: "test_service"},
24572448
},
24582449
samplingConfig: &sampling.Config{
24592450
UsageGroups: map[string]sampling.UsageGroupSampling{
24602451
"${labels.service_name}": {Probability: 1.0},
2461-
"test_service": {Probability: 1.0},
2452+
"test_service": {Probability: 0.0},
24622453
},
24632454
},
2464-
expected: true,
2455+
expected: false,
24652456
expectedMatch: &sampling.Source{
24662457
UsageGroup: "test_service",
2467-
Probability: 1.0,
2458+
Probability: 0.0,
2459+
},
2460+
},
2461+
{
2462+
name: "single usage group, multiple sampling rules - should prioritize specific rule",
2463+
groups: []validation.UsageGroupMatchName{
2464+
{ConfiguredName: "${labels.service_name}", ResolvedName: "test_service"},
2465+
},
2466+
samplingConfig: &sampling.Config{
2467+
UsageGroups: map[string]sampling.UsageGroupSampling{
2468+
"${labels.service_name}": {Probability: 1.0},
2469+
"test_service": {Probability: 0.0},
2470+
},
2471+
},
2472+
expected: false,
2473+
expectedMatch: &sampling.Source{
2474+
UsageGroup: "test_service",
2475+
Probability: 0.0,
24682476
},
24692477
},
24702478
}
@@ -2474,13 +2482,13 @@ func TestDistributor_shouldSample(t *testing.T) {
24742482
overrides := validation.MockOverrides(func(defaults *validation.Limits, tenantLimits map[string]*validation.Limits) {
24752483
l := validation.MockDefaultLimits()
24762484
l.DistributorSampling = tt.samplingConfig
2477-
tenantLimits[tt.tenantID] = l
2485+
tenantLimits["test-tenant"] = l
24782486
})
24792487
d := &Distributor{
24802488
limits: overrides,
24812489
}
24822490

2483-
sample, match := d.shouldSample(tt.tenantID, tt.groups)
2491+
sample, match := d.shouldSample("test-tenant", tt.groups)
24842492
assert.Equal(t, tt.expected, sample)
24852493
assert.Equal(t, tt.expectedMatch, match)
24862494
})
@@ -2491,30 +2499,39 @@ func TestDistributor_shouldSample_Probability(t *testing.T) {
24912499
tests := []struct {
24922500
name string
24932501
probability float64
2502+
usageGroups []validation.UsageGroupMatchName
24942503
}{
24952504
{
24962505
name: "30% sampling rate",
24972506
probability: 0.3,
2507+
usageGroups: []validation.UsageGroupMatchName{{ConfiguredName: "${labels.service_name}", ResolvedName: "test-service-1"}},
24982508
},
24992509
{
25002510
name: "70% sampling rate",
25012511
probability: 0.7,
2512+
usageGroups: []validation.UsageGroupMatchName{{ConfiguredName: "${labels.service_name}", ResolvedName: "test-service-1"}},
25022513
},
25032514
{
25042515
name: "10% sampling rate",
25052516
probability: 0.1,
2517+
usageGroups: []validation.UsageGroupMatchName{{ConfiguredName: "${labels.service_name}", ResolvedName: "test-service-1"}},
2518+
},
2519+
{
2520+
name: "0% sampling rate for the baseline group",
2521+
probability: 0.0,
2522+
usageGroups: []validation.UsageGroupMatchName{{ConfiguredName: "${labels.service_name}", ResolvedName: "test-service-2"}},
25062523
},
25072524
}
25082525

25092526
const iterations = 10000
25102527
tenantID := "test-tenant"
2511-
groups := []validation.UsageGroupMatchName{{ConfiguredName: "test-group", ResolvedName: "test-group"}}
25122528

25132529
for _, tt := range tests {
25142530
t.Run(tt.name, func(t *testing.T) {
25152531
samplingConfig := &sampling.Config{
25162532
UsageGroups: map[string]sampling.UsageGroupSampling{
2517-
"test-group": {Probability: tt.probability},
2533+
"${labels.service_name}": {Probability: 0.0}, // we drop all profiles by default
2534+
"test-service-1": {Probability: tt.probability},
25182535
},
25192536
}
25202537

@@ -2529,7 +2546,7 @@ func TestDistributor_shouldSample_Probability(t *testing.T) {
25292546

25302547
accepted := 0
25312548
for i := 0; i < iterations; i++ {
2532-
if s, _ := d.shouldSample(tenantID, groups); s {
2549+
if s, _ := d.shouldSample(tenantID, tt.usageGroups); s {
25332550
accepted++
25342551
}
25352552
}

0 commit comments

Comments
 (0)