Skip to content

Commit a3ab0e4

Browse files
committed
Add a query result limit to regex matcher
Signed-off-by: SungJin1212 <[email protected]>
1 parent 16a2f54 commit a3ab0e4

File tree

9 files changed

+35
-14
lines changed

9 files changed

+35
-14
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.
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

docs/configuration/config-file-reference.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,9 @@ tenant_federation:
177177
# CLI flag: -tenant-federation.max-concurrent
178178
[max_concurrent: <int> | default = 16]
179179

180-
# A maximum number of tenants to query at once. 0 means no limit.
180+
# A maximum number of tenants to query at once. 0 means no limit. If
181+
# `-tenant-federation.regex-matcher-enabled` is enabled and this limit is
182+
# greater than 0, the number of tenants to query is adjusted to this value.
181183
# CLI flag: -tenant-federation.max-tenant
182184
[max_tenant: <int> | default = 0]
183185

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/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: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ type RegexResolver struct {
3232

3333
knownUsers []string
3434
userSyncInterval time.Duration
35+
maxTenant int
3536
userScanner users.Scanner
3637
logger log.Logger
3738
sync.Mutex
@@ -42,7 +43,7 @@ type RegexResolver struct {
4243
discoveredUsers prometheus.Gauge
4344
}
4445

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) {
46+
func NewRegexResolver(cfg tsdb.UsersScannerConfig, tenantFederationCfg Config, reg prometheus.Registerer, bucketClientFactory func(ctx context.Context) (objstore.InstrumentedBucket, error), logger log.Logger) (*RegexResolver, error) {
4647
bucketClient, err := bucketClientFactory(context.Background())
4748
if err != nil {
4849
return nil, errors.Wrap(err, "failed to create the bucket client")
@@ -54,7 +55,8 @@ func NewRegexResolver(cfg tsdb.UsersScannerConfig, reg prometheus.Registerer, bu
5455
}
5556

5657
r := &RegexResolver{
57-
userSyncInterval: userSyncInterval,
58+
userSyncInterval: tenantFederationCfg.UserSyncInterval,
59+
maxTenant: tenantFederationCfg.MaxTenant,
5860
userScanner: userScanner,
5961
logger: logger,
6062
}
@@ -160,6 +162,11 @@ func (r *RegexResolver) getRegexMatchedOrgIds(orgID string) ([]string, error) {
160162
return []string{"fake"}, nil
161163
}
162164

165+
if r.maxTenant > 0 && len(matched) > r.maxTenant {
166+
// adjust matched tenants to maxTenant
167+
matched = matched[:r.maxTenant]
168+
}
169+
163170
return matched, nil
164171
}
165172

pkg/querier/tenantfederation/regex_resolver_test.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ func Test_RegexResolver(t *testing.T) {
2525
orgID string
2626
expectedErr error
2727
expectedOrgIDs []string
28+
maxTenants int
2829
}{
2930
{
3031
description: "invalid regex",
@@ -62,6 +63,13 @@ func Test_RegexResolver(t *testing.T) {
6263
orgID: "user-1|user-2",
6364
expectedOrgIDs: []string{"user-1"},
6465
},
66+
{
67+
description: "adjust maxTenant",
68+
existingTenants: []string{"user-1", "user-2", "user-3"},
69+
orgID: "user-.+",
70+
expectedOrgIDs: []string{"user-1", "user-2"},
71+
maxTenants: 2,
72+
},
6573
}
6674

6775
for _, tc := range tests {
@@ -80,7 +88,8 @@ func Test_RegexResolver(t *testing.T) {
8088
}
8189

8290
usersScannerConfig := cortex_tsdb.UsersScannerConfig{Strategy: cortex_tsdb.UserScanStrategyList}
83-
regexResolver, err := NewRegexResolver(usersScannerConfig, reg, bucketClientFactory, time.Second, log.NewNopLogger())
91+
tenantFederationConfig := Config{UserSyncInterval: time.Second, MaxTenant: tc.maxTenants}
92+
regexResolver, err := NewRegexResolver(usersScannerConfig, tenantFederationConfig, reg, bucketClientFactory, log.NewNopLogger())
8493
require.NoError(t, err)
8594
require.NoError(t, services.StartAndAwaitRunning(context.Background(), regexResolver))
8695

pkg/querier/tenantfederation/tenant_federation.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ type Config struct {
2121
func (cfg *Config) RegisterFlags(f *flag.FlagSet) {
2222
f.BoolVar(&cfg.Enabled, "tenant-federation.enabled", false, "If enabled on all Cortex services, queries can be federated across multiple tenants. The tenant IDs involved need to be specified separated by a `|` character in the `X-Scope-OrgID` header (experimental).")
2323
f.IntVar(&cfg.MaxConcurrent, "tenant-federation.max-concurrent", defaultMaxConcurrency, "The number of workers used to process each federated query.")
24-
f.IntVar(&cfg.MaxTenant, "tenant-federation.max-tenant", 0, "A maximum number of tenants to query at once. 0 means no limit.")
24+
f.IntVar(&cfg.MaxTenant, "tenant-federation.max-tenant", 0, "A maximum number of tenants to query at once. 0 means no limit. If `-tenant-federation.regex-matcher-enabled` is enabled and this limit is greater than 0, the number of tenants to query is adjusted to this value.")
2525
f.BoolVar(&cfg.RegexMatcherEnabled, "tenant-federation.regex-matcher-enabled", false, "[Experimental] If enabled, the `X-Scope-OrgID` header value can accept a regex and the matched tenantIDs are automatically involved. The regex matching rule follows the Prometheus, see the detail: https://prometheus.io/docs/prometheus/latest/querying/basics/#regular-expressions. The user discovery is based on scanning block storage, so new users can get queries after uploading a block (generally 2h).")
2626
f.DurationVar(&cfg.UserSyncInterval, "tenant-federation.user-sync-interval", time.Minute*5, "[Experimental] If the regex matcher is enabled, it specifies how frequently to scan users. The scanned users are used to calculate matched tenantIDs. The scanning strategy depends on the `-blocks-storage.users-scanner.strategy`.")
2727
}

0 commit comments

Comments
 (0)