github.com/netdata/go.d.plugin@v0.58.1/pkg/prometheus/selector/parse.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package selector 4 5 import ( 6 "fmt" 7 "regexp" 8 "strings" 9 10 "github.com/netdata/go.d.plugin/pkg/matcher" 11 ) 12 13 var ( 14 reLV = regexp.MustCompile(`^(?P<label_name>[a-zA-Z0-9_]+)(?P<op>=~|!~|=\*|!\*|=|!=)"(?P<pattern>.+)"$`) 15 ) 16 17 func Parse(expr string) (Selector, error) { 18 var srs []Selector 19 lvs := strings.Split(unsugarExpr(expr), ",") 20 21 for _, lv := range lvs { 22 sr, err := parseSelector(lv) 23 if err != nil { 24 return nil, err 25 } 26 srs = append(srs, sr) 27 } 28 29 switch len(srs) { 30 case 0: 31 return nil, nil 32 case 1: 33 return srs[0], nil 34 default: 35 return And(srs[0], srs[1], srs[2:]...), nil 36 } 37 } 38 39 func parseSelector(line string) (Selector, error) { 40 sub := reLV.FindStringSubmatch(strings.TrimSpace(line)) 41 if sub == nil { 42 return nil, fmt.Errorf("invalid selector syntax: '%s'", line) 43 } 44 45 name, op, pattern := sub[1], sub[2], strings.Trim(sub[3], "\"") 46 47 var m matcher.Matcher 48 var err error 49 50 switch op { 51 case OpEqual, OpNegEqual: 52 m, err = matcher.NewStringMatcher(pattern, true, true) 53 case OpRegexp, OpNegRegexp: 54 m, err = matcher.NewRegExpMatcher(pattern) 55 case OpSimplePatterns, OpNegSimplePatterns: 56 m, err = matcher.NewSimplePatternsMatcher(pattern) 57 default: 58 err = fmt.Errorf("unknown matching operator: %s", op) 59 } 60 if err != nil { 61 return nil, err 62 } 63 64 sr := labelSelector{ 65 name: name, 66 m: m, 67 } 68 69 if neg := strings.HasPrefix(op, "!"); neg { 70 return Not(sr), nil 71 } 72 return sr, nil 73 } 74 75 func unsugarExpr(expr string) string { 76 // name => __name__=*"name" 77 // name{label="value"} => __name__=*"name",label="value" 78 // {label="value"} => label="value" 79 expr = strings.TrimSpace(expr) 80 81 switch idx := strings.IndexByte(expr, '{'); true { 82 case idx == -1: 83 expr = fmt.Sprintf(`__name__%s"%s"`, 84 OpSimplePatterns, 85 strings.TrimSpace(expr), 86 ) 87 case idx == 0: 88 expr = strings.Trim(expr, "{}") 89 default: 90 expr = fmt.Sprintf(`__name__%s"%s",%s`, 91 OpSimplePatterns, 92 strings.TrimSpace(expr[:idx]), 93 strings.Trim(expr[idx:], "{}"), 94 ) 95 } 96 return expr 97 }