mirror of
https://github.com/grafana/grafana.git
synced 2025-01-24 15:27:01 -06:00
1ab8208e07
--------- Co-authored-by: ismail simsek <ismailsimsek09@gmail.com>
106 lines
2.5 KiB
Go
106 lines
2.5 KiB
Go
package models
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/prometheus/prometheus/model/labels"
|
|
"github.com/prometheus/prometheus/promql/parser"
|
|
)
|
|
|
|
func ApplyFiltersAndGroupBy(rawExpr string, scopeFilters, adHocFilters []ScopeFilter, groupBy []string) (string, error) {
|
|
expr, err := parser.ParseExpr(rawExpr)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
matchers, err := filtersToMatchers(scopeFilters, adHocFilters)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
matcherNamesToIdx := make(map[string]int, len(matchers))
|
|
for i, matcher := range matchers {
|
|
if matcher == nil {
|
|
continue
|
|
}
|
|
matcherNamesToIdx[matcher.Name] = i
|
|
}
|
|
|
|
parser.Inspect(expr, func(node parser.Node, nodes []parser.Node) error {
|
|
switch v := node.(type) {
|
|
case *parser.VectorSelector:
|
|
found := make([]bool, len(matchers))
|
|
for _, matcher := range v.LabelMatchers {
|
|
if matcher == nil || matcher.Name == "__name__" { // const prob
|
|
continue
|
|
}
|
|
if _, ok := matcherNamesToIdx[matcher.Name]; ok {
|
|
found[matcherNamesToIdx[matcher.Name]] = true
|
|
newM := matchers[matcherNamesToIdx[matcher.Name]]
|
|
matcher.Name = newM.Name
|
|
matcher.Type = newM.Type
|
|
matcher.Value = newM.Value
|
|
}
|
|
}
|
|
for i, f := range found {
|
|
if f {
|
|
continue
|
|
}
|
|
v.LabelMatchers = append(v.LabelMatchers, matchers[i])
|
|
}
|
|
|
|
return nil
|
|
case *parser.AggregateExpr:
|
|
found := make(map[string]bool)
|
|
for _, lName := range v.Grouping {
|
|
found[lName] = true
|
|
}
|
|
for _, k := range groupBy {
|
|
if !found[k] {
|
|
v.Grouping = append(v.Grouping, k)
|
|
}
|
|
}
|
|
return nil
|
|
default:
|
|
return nil
|
|
}
|
|
})
|
|
return expr.String(), nil
|
|
}
|
|
|
|
func filtersToMatchers(scopeFilters, adhocFilters []ScopeFilter) ([]*labels.Matcher, error) {
|
|
filterMap := make(map[string]*labels.Matcher)
|
|
|
|
for _, filter := range append(scopeFilters, adhocFilters...) {
|
|
matcher, err := filterToMatcher(filter)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
filterMap[filter.Key] = matcher
|
|
}
|
|
|
|
matchers := make([]*labels.Matcher, 0, len(filterMap))
|
|
for _, matcher := range filterMap {
|
|
matchers = append(matchers, matcher)
|
|
}
|
|
|
|
return matchers, nil
|
|
}
|
|
|
|
func filterToMatcher(f ScopeFilter) (*labels.Matcher, error) {
|
|
var mt labels.MatchType
|
|
switch f.Operator {
|
|
case FilterOperatorEquals:
|
|
mt = labels.MatchEqual
|
|
case FilterOperatorNotEquals:
|
|
mt = labels.MatchNotEqual
|
|
case FilterOperatorRegexMatch:
|
|
mt = labels.MatchRegexp
|
|
case FilterOperatorRegexNotMatch:
|
|
mt = labels.MatchNotRegexp
|
|
default:
|
|
return nil, fmt.Errorf("unknown operator %q", f.Operator)
|
|
}
|
|
return labels.NewMatcher(mt, f.Key, f.Value)
|
|
}
|