mirror of
https://github.com/grafana/grafana.git
synced 2025-08-01 13:22:21 +08:00
Scopes: Merge scopes filters with OR condition in case they overlap. (#97276)
Signed-off-by: bergquist <carl.bergquist@gmail.com>
This commit is contained in:
@ -73,11 +73,31 @@ func ApplyFiltersAndGroupBy(rawExpr string, scopeFilters, adHocFilters []ScopeFi
|
|||||||
func FiltersToMatchers(scopeFilters, adhocFilters []ScopeFilter) ([]*labels.Matcher, error) {
|
func FiltersToMatchers(scopeFilters, adhocFilters []ScopeFilter) ([]*labels.Matcher, error) {
|
||||||
filterMap := make(map[string]*labels.Matcher)
|
filterMap := make(map[string]*labels.Matcher)
|
||||||
|
|
||||||
for _, filter := range append(scopeFilters, adhocFilters...) {
|
// scope filters are applied first
|
||||||
|
for _, filter := range scopeFilters {
|
||||||
matcher, err := filterToMatcher(filter)
|
matcher, err := filterToMatcher(filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// when scopes have the same key, both values should be matched
|
||||||
|
// in prometheus that means using an regex with both values
|
||||||
|
if _, ok := filterMap[filter.Key]; ok {
|
||||||
|
filterMap[filter.Key].Value = filterMap[filter.Key].Value + "|" + matcher.Value
|
||||||
|
filterMap[filter.Key].Type = labels.MatchRegexp
|
||||||
|
} else {
|
||||||
|
filterMap[filter.Key] = matcher
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ad hoc filters are applied after scope filters
|
||||||
|
for _, filter := range adhocFilters {
|
||||||
|
matcher, err := filterToMatcher(filter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// when ad hoc filters have the same key, the last one should be used
|
||||||
filterMap[filter.Key] = matcher
|
filterMap[filter.Key] = matcher
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,6 +106,29 @@ func TestApplyQueryFiltersAndGroupBy_Filters(t *testing.T) {
|
|||||||
expected: `{__name__="http_requests_total",namespace="istio"}`,
|
expected: `{__name__="http_requests_total",namespace="istio"}`,
|
||||||
expectErr: false,
|
expectErr: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "merge scopes filters into using OR if they share filter key",
|
||||||
|
query: `http_requests_total{}`,
|
||||||
|
scopeFilters: []ScopeFilter{
|
||||||
|
{Key: "namespace", Value: "default", Operator: FilterOperatorEquals},
|
||||||
|
{Key: "namespace", Value: "kube-system", Operator: FilterOperatorEquals},
|
||||||
|
},
|
||||||
|
expected: `http_requests_total{namespace=~"default|kube-system"}`,
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "adhoc filters win over scope filters if they share filter key",
|
||||||
|
query: `http_requests_total{}`,
|
||||||
|
scopeFilters: []ScopeFilter{
|
||||||
|
{Key: "namespace", Value: "default", Operator: FilterOperatorEquals},
|
||||||
|
{Key: "namespace", Value: "kube-system", Operator: FilterOperatorEquals},
|
||||||
|
},
|
||||||
|
adhocFilters: []ScopeFilter{
|
||||||
|
{Key: "namespace", Value: "adhoc-wins", Operator: FilterOperatorEquals},
|
||||||
|
},
|
||||||
|
expected: `http_requests_total{namespace="adhoc-wins"}`,
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
@ -116,7 +139,7 @@ func TestApplyQueryFiltersAndGroupBy_Filters(t *testing.T) {
|
|||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
} else {
|
} else {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, tt.expected, expr)
|
require.Equal(t, tt.expected, expr, tt.name)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user