Skip to content

Commit 7e0ca92

Browse files
committed
Implement maxTanant lmit on regex matcher
Signed-off-by: SungJin1212 <[email protected]>
1 parent 6c7457d commit 7e0ca92

File tree

8 files changed

+37
-16
lines changed

8 files changed

+37
-16
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
* [FEATURE] Distributor/Ingester: Implemented experimental feature to use gRPC stream connection for push requests. This can be enabled by setting `-distributor.use-stream-push=true`. #6580
1919
* [FEATURE] Compactor: Add support for percentage based sharding for compactors. #6738
2020
* [FEATURE] Querier: Allow choosing PromQL engine via header. #6777
21+
* [ENHANCEMENT] Tenant Federation: Add a # of query result limit logic when the `-tenant-federation.regex-matcher-enabled` is enabled. #6845
2122
* [ENHANCEMENT] Query Frontend: Change to return 400 when the tenant resolving fail. #6715
2223
* [ENHANCEMENT] Querier: Support query parameters to metadata api (/api/v1/metadata) to allow user to limit metadata to return. Add a `-ingester.return-all-metadata` flag to make the metadata API run when the deployment. Please set this flag to `false` to use the metadata API with the limits later. #6681 #6744
2324
* [ENHANCEMENT] Ingester: Add a `cortex_ingester_active_native_histogram_series` metric to track # of active NH series. #6695

pkg/cortex/modules.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ func (t *Cortex) initTenantFederation() (serv services.Service, err error) {
295295
return bucket.NewClient(ctx, t.Cfg.BlocksStorage.Bucket, nil, "regex-resolver", util_log.Logger, prometheus.DefaultRegisterer)
296296
}
297297

298-
regexResolver, err := tenantfederation.NewRegexResolver(t.Cfg.BlocksStorage.UsersScanner, prometheus.DefaultRegisterer, bucketClientFactory, t.Cfg.TenantFederation.UserSyncInterval, util_log.Logger)
298+
regexResolver, err := tenantfederation.NewRegexResolver(t.Cfg.BlocksStorage.UsersScanner, t.Cfg.TenantFederation, prometheus.DefaultRegisterer, bucketClientFactory, util_log.Logger)
299299
if err != nil {
300300
return nil, fmt.Errorf("failed to initialize regex resolver: %v", err)
301301
}

pkg/frontend/transport/handler.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@ const (
3535
// StatusClientClosedRequest is the status code for when a client request cancellation of a http request
3636
StatusClientClosedRequest = 499
3737
ServiceTimingHeaderName = "Server-Timing"
38-
39-
errTooManyTenants = "too many tenants, max: %d, actual: %d"
4038
)
4139

4240
var (
@@ -234,7 +232,7 @@ func (f *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
234232
if f.cfg.QueryStatsEnabled {
235233
f.rejectedQueries.WithLabelValues(reasonTooManyTenants, source, userID).Inc()
236234
}
237-
http.Error(w, fmt.Errorf(errTooManyTenants, maxTenant, len(tenantIDs)).Error(), http.StatusBadRequest)
235+
http.Error(w, fmt.Errorf(tenantfederation.ErrTooManyTenants, maxTenant, len(tenantIDs)).Error(), http.StatusBadRequest)
238236
return
239237
}
240238
}

pkg/querier/tenantfederation/exemplar_merge_queryable_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,8 @@ func Test_MergeExemplarQuerier_Select_WhenUseRegexResolver(t *testing.T) {
335335
}
336336

337337
usersScannerConfig := cortex_tsdb.UsersScannerConfig{Strategy: cortex_tsdb.UserScanStrategyList}
338-
regexResolver, err := NewRegexResolver(usersScannerConfig, reg, bucketClientFactory, time.Second, log.NewNopLogger())
338+
tenantFederationConfig := Config{UserSyncInterval: time.Second}
339+
regexResolver, err := NewRegexResolver(usersScannerConfig, tenantFederationConfig, reg, bucketClientFactory, log.NewNopLogger())
339340
require.NoError(t, err)
340341
tenant.WithDefaultResolver(regexResolver)
341342
require.NoError(t, services.StartAndAwaitRunning(context.Background(), regexResolver))

pkg/querier/tenantfederation/merge_queryable_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -677,8 +677,8 @@ func TestMergeQueryable_Select(t *testing.T) {
677677
}
678678

679679
usersScannerConfig := cortex_tsdb.UsersScannerConfig{Strategy: cortex_tsdb.UserScanStrategyList}
680-
681-
regexResolver, err := NewRegexResolver(usersScannerConfig, reg, bucketClientFactory, time.Second, log.NewNopLogger())
680+
tenantFederationConfig := Config{UserSyncInterval: time.Second}
681+
regexResolver, err := NewRegexResolver(usersScannerConfig, tenantFederationConfig, reg, bucketClientFactory, log.NewNopLogger())
682682
require.NoError(t, err)
683683

684684
// set a regex tenant resolver
@@ -876,8 +876,8 @@ func TestMergeQueryable_LabelNames(t *testing.T) {
876876
return bucketClient, nil
877877
}
878878
usersScannerConfig := cortex_tsdb.UsersScannerConfig{Strategy: cortex_tsdb.UserScanStrategyList}
879-
880-
regexResolver, err := NewRegexResolver(usersScannerConfig, reg, bucketClientFactory, time.Second, log.NewNopLogger())
879+
tenantFederationConfig := Config{UserSyncInterval: time.Second}
880+
regexResolver, err := NewRegexResolver(usersScannerConfig, tenantFederationConfig, reg, bucketClientFactory, log.NewNopLogger())
881881
require.NoError(t, err)
882882

883883
// set a regex tenant resolver
@@ -1114,8 +1114,8 @@ func TestMergeQueryable_LabelValues(t *testing.T) {
11141114
return bucketClient, nil
11151115
}
11161116
usersScannerConfig := cortex_tsdb.UsersScannerConfig{Strategy: cortex_tsdb.UserScanStrategyList}
1117-
1118-
regexResolver, err := NewRegexResolver(usersScannerConfig, reg, bucketClientFactory, time.Second, log.NewNopLogger())
1117+
tenantFederationConfig := Config{UserSyncInterval: time.Second}
1118+
regexResolver, err := NewRegexResolver(usersScannerConfig, tenantFederationConfig, reg, bucketClientFactory, log.NewNopLogger())
11191119
require.NoError(t, err)
11201120

11211121
// set a regex tenant resolver

pkg/querier/tenantfederation/metadata_merge_querier_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,8 @@ func Test_mergeMetadataQuerier_MetricsMetadata_WhenUseRegexResolver(t *testing.T
169169
}
170170

171171
usersScannerConfig := cortex_tsdb.UsersScannerConfig{Strategy: cortex_tsdb.UserScanStrategyList}
172-
regexResolver, err := NewRegexResolver(usersScannerConfig, reg, bucketClientFactory, time.Second, log.NewNopLogger())
172+
tenantFederationConfig := Config{UserSyncInterval: time.Second}
173+
regexResolver, err := NewRegexResolver(usersScannerConfig, tenantFederationConfig, reg, bucketClientFactory, log.NewNopLogger())
173174
require.NoError(t, err)
174175
tenant.WithDefaultResolver(regexResolver)
175176
require.NoError(t, services.StartAndAwaitRunning(context.Background(), regexResolver))

pkg/querier/tenantfederation/regex_resolver.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package tenantfederation
22

33
import (
44
"context"
5+
"fmt"
6+
"net/http"
57
"sort"
68
"sync"
79
"time"
@@ -14,6 +16,7 @@ import (
1416
"github.com/prometheus/prometheus/model/labels"
1517
"github.com/thanos-io/objstore"
1618
"github.com/thanos-io/thanos/pkg/extprom"
19+
"github.com/weaveworks/common/httpgrpc"
1720
"github.com/weaveworks/common/user"
1821

1922
"github.com/cortexproject/cortex/pkg/storage/tsdb"
@@ -24,6 +27,8 @@ import (
2427

2528
var (
2629
errInvalidRegex = errors.New("invalid regex present")
30+
31+
ErrTooManyTenants = "too many tenants, max: %d, actual: %d"
2732
)
2833

2934
// RegexResolver resolves tenantIDs matched given regex.
@@ -32,6 +37,7 @@ type RegexResolver struct {
3237

3338
knownUsers []string
3439
userSyncInterval time.Duration
40+
maxTenant int
3541
userScanner users.Scanner
3642
logger log.Logger
3743
sync.Mutex
@@ -42,7 +48,7 @@ type RegexResolver struct {
4248
discoveredUsers prometheus.Gauge
4349
}
4450

45-
func NewRegexResolver(cfg tsdb.UsersScannerConfig, reg prometheus.Registerer, bucketClientFactory func(ctx context.Context) (objstore.InstrumentedBucket, error), userSyncInterval time.Duration, logger log.Logger) (*RegexResolver, error) {
51+
func NewRegexResolver(cfg tsdb.UsersScannerConfig, tenantFederationCfg Config, reg prometheus.Registerer, bucketClientFactory func(ctx context.Context) (objstore.InstrumentedBucket, error), logger log.Logger) (*RegexResolver, error) {
4652
bucketClient, err := bucketClientFactory(context.Background())
4753
if err != nil {
4854
return nil, errors.Wrap(err, "failed to create the bucket client")
@@ -54,7 +60,8 @@ func NewRegexResolver(cfg tsdb.UsersScannerConfig, reg prometheus.Registerer, bu
5460
}
5561

5662
r := &RegexResolver{
57-
userSyncInterval: userSyncInterval,
63+
userSyncInterval: tenantFederationCfg.UserSyncInterval,
64+
maxTenant: tenantFederationCfg.MaxTenant,
5865
userScanner: userScanner,
5966
logger: logger,
6067
}
@@ -160,6 +167,10 @@ func (r *RegexResolver) getRegexMatchedOrgIds(orgID string) ([]string, error) {
160167
return []string{"fake"}, nil
161168
}
162169

170+
if r.maxTenant > 0 && len(matched) > r.maxTenant {
171+
return nil, httpgrpc.Errorf(http.StatusBadRequest, "%s", fmt.Errorf(ErrTooManyTenants, r.maxTenant, len(matched)).Error())
172+
}
173+
163174
return matched, nil
164175
}
165176

pkg/querier/tenantfederation/regex_resolver_test.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ func Test_RegexResolver(t *testing.T) {
2727
orgID string
2828
expectedErr error
2929
expectedOrgIDs []string
30+
maxTenants int
3031
}{
3132
{
3233
description: "invalid regex",
@@ -64,6 +65,13 @@ func Test_RegexResolver(t *testing.T) {
6465
orgID: "user-1|user-2",
6566
expectedOrgIDs: []string{"user-1"},
6667
},
68+
{
69+
description: "adjust maxTenant",
70+
existingTenants: []string{"user-1", "user-2", "user-3"},
71+
orgID: "user-.+",
72+
maxTenants: 2,
73+
expectedErr: errors.New("too many tenants, max: 2, actual: 3"),
74+
},
6775
}
6876

6977
for _, tc := range tests {
@@ -82,7 +90,8 @@ func Test_RegexResolver(t *testing.T) {
8290
}
8391

8492
usersScannerConfig := cortex_tsdb.UsersScannerConfig{Strategy: cortex_tsdb.UserScanStrategyList}
85-
regexResolver, err := NewRegexResolver(usersScannerConfig, reg, bucketClientFactory, time.Second, log.NewNopLogger())
93+
tenantFederationConfig := Config{UserSyncInterval: time.Second, MaxTenant: tc.maxTenants}
94+
regexResolver, err := NewRegexResolver(usersScannerConfig, tenantFederationConfig, reg, bucketClientFactory, log.NewNopLogger())
8695
require.NoError(t, err)
8796
require.NoError(t, services.StartAndAwaitRunning(context.Background(), regexResolver))
8897

@@ -97,7 +106,7 @@ func Test_RegexResolver(t *testing.T) {
97106
orgIDs, err := regexResolver.TenantIDs(ctx)
98107

99108
if tc.expectedErr != nil {
100-
require.Error(t, err)
109+
require.Contains(t, err.Error(), tc.expectedErr.Error())
101110
} else {
102111
require.NoError(t, err)
103112
require.Equal(t, tc.expectedOrgIDs, orgIDs)

0 commit comments

Comments
 (0)