github.com/influxdata/telegraf@v1.30.3/filter/filter.go (about) 1 package filter 2 3 import ( 4 "strings" 5 6 "github.com/gobwas/glob" 7 ) 8 9 type Filter interface { 10 Match(string) bool 11 } 12 13 // Compile takes a list of string filters and returns a Filter interface 14 // for matching a given string against the filter list. The filter list 15 // supports glob matching with separators too, ie: 16 // 17 // f, _ := Compile([]string{"cpu", "mem", "net*"}) 18 // f.Match("cpu") // true 19 // f.Match("network") // true 20 // f.Match("memory") // false 21 // 22 // separators are only to be used for globbing filters, ie: 23 // 24 // f, _ := Compile([]string{"cpu.*.count"}, '.') 25 // f.Match("cpu.count") // false 26 // f.Match("cpu.measurement.count") // true 27 // f.Match("cpu.field.measurement.count") // false 28 // 29 // Compile will return nil if the filter list is empty. 30 func Compile(filters []string, separators ...rune) (Filter, error) { 31 // return if there is nothing to compile 32 if len(filters) == 0 { 33 return nil, nil 34 } 35 36 // check if we can compile a non-glob filter 37 noGlob := len(separators) == 0 38 for _, filter := range filters { 39 if hasMeta(filter) { 40 noGlob = false 41 break 42 } 43 } 44 45 switch { 46 case noGlob: 47 // return non-globbing filter if not needed. 48 return compileFilterNoGlob(filters), nil 49 case len(filters) == 1: 50 return glob.Compile(filters[0], separators...) 51 default: 52 return glob.Compile("{"+strings.Join(filters, ",")+"}", separators...) 53 } 54 } 55 56 func MustCompile(filters []string, separators ...rune) Filter { 57 f, err := Compile(filters, separators...) 58 if err != nil { 59 panic(err) 60 } 61 return f 62 } 63 64 // hasMeta reports whether path contains any magic glob characters. 65 func hasMeta(s string) bool { 66 return strings.ContainsAny(s, "*?[") 67 } 68 69 type filter struct { 70 m map[string]struct{} 71 } 72 73 func (f *filter) Match(s string) bool { 74 _, ok := f.m[s] 75 return ok 76 } 77 78 type filtersingle struct { 79 s string 80 } 81 82 func (f *filtersingle) Match(s string) bool { 83 return f.s == s 84 } 85 86 func compileFilterNoGlob(filters []string) Filter { 87 if len(filters) == 1 { 88 return &filtersingle{s: filters[0]} 89 } 90 out := filter{m: make(map[string]struct{})} 91 for _, filter := range filters { 92 out.m[filter] = struct{}{} 93 } 94 return &out 95 } 96 97 type IncludeExcludeFilter struct { 98 include Filter 99 exclude Filter 100 includeDefault bool 101 excludeDefault bool 102 } 103 104 func NewIncludeExcludeFilter( 105 include []string, 106 exclude []string, 107 ) (Filter, error) { 108 return NewIncludeExcludeFilterDefaults(include, exclude, true, false) 109 } 110 111 func NewIncludeExcludeFilterDefaults( 112 include []string, 113 exclude []string, 114 includeDefault bool, 115 excludeDefault bool, 116 ) (Filter, error) { 117 in, err := Compile(include) 118 if err != nil { 119 return nil, err 120 } 121 122 ex, err := Compile(exclude) 123 if err != nil { 124 return nil, err 125 } 126 127 return &IncludeExcludeFilter{in, ex, includeDefault, excludeDefault}, nil 128 } 129 130 func (f *IncludeExcludeFilter) Match(s string) bool { 131 if f.include != nil { 132 if !f.include.Match(s) { 133 return false 134 } 135 } else if !f.includeDefault { 136 return false 137 } 138 139 if f.exclude != nil { 140 if f.exclude.Match(s) { 141 return false 142 } 143 } else if f.excludeDefault { 144 return false 145 } 146 147 return true 148 }