Permit regex ignores. Fixes #18

This commit is contained in:
ppom 2023-08-21 23:33:56 +02:00
parent 075b9252b7
commit b3791319d8
4 changed files with 69 additions and 29 deletions

View File

@ -42,18 +42,29 @@ func cmdStdout(commandline []string) chan *string {
return lines return lines
} }
func (p *Pattern) notAnIgnore(match *string) bool {
for _, ignore := range p.Ignore {
if ignore == *match {
return false
}
}
return true
}
// Whether one of the filter's regexes is matched on a line // Whether one of the filter's regexes is matched on a line
func (f *Filter) match(line *string) string { func (f *Filter) match(line *string) string {
for _, regex := range f.compiledRegex { for _, regex := range f.compiledRegex {
if matches := regex.FindStringSubmatch(*line); matches != nil { if matches := regex.FindStringSubmatch(*line); matches != nil {
match := matches[regex.SubexpIndex(f.patternName)] match := matches[regex.SubexpIndex(f.pattern.name)]
if f.pattern.notAnIgnore(&match) {
log.Printf("INFO %s.%s: match [%v]\n", f.stream.name, f.name, match) log.Printf("INFO %s.%s: match [%v]\n", f.stream.name, f.name, match)
return match return match
} }
} }
}
return "" return ""
} }
@ -94,7 +105,7 @@ func (a *Action) exec(match string, advance time.Duration) {
if doExec { if doExec {
computedCommand := make([]string, 0, len(a.Cmd)) computedCommand := make([]string, 0, len(a.Cmd))
for _, item := range a.Cmd { for _, item := range a.Cmd {
computedCommand = append(computedCommand, strings.ReplaceAll(item, a.filter.patternWithBraces, match)) computedCommand = append(computedCommand, strings.ReplaceAll(item, a.filter.pattern.nameWithBraces, match))
} }
log.Printf("INFO %s.%s.%s: run %s\n", a.filter.stream.name, a.filter.name, a.name, computedCommand) log.Printf("INFO %s.%s.%s: run %s\n", a.filter.stream.name, a.filter.name, a.name, computedCommand)

View File

@ -15,10 +15,18 @@ import (
) )
type Conf struct { type Conf struct {
Patterns map[string]string `yaml:"patterns"` Patterns map[string]*Pattern `yaml:"patterns"`
Streams map[string]*Stream `yaml:"streams"` Streams map[string]*Stream `yaml:"streams"`
} }
type Pattern struct {
Regex string `yaml:"regex"`
Ignore []string `yaml:"ignore"`
name string `yaml:"-"`
nameWithBraces string `yaml:"-"`
}
// Stream, Filter & Action structures must never be copied. // Stream, Filter & Action structures must never be copied.
// They're always referenced through pointers // They're always referenced through pointers
@ -35,8 +43,7 @@ type Filter struct {
Regex []string `yaml:"regex"` Regex []string `yaml:"regex"`
compiledRegex []regexp.Regexp `yaml:"-"` compiledRegex []regexp.Regexp `yaml:"-"`
patternName string `yaml:"-"` pattern *Pattern `yaml:"-"`
patternWithBraces string `yaml:"-"`
Retry int `yaml:"retry"` Retry int `yaml:"retry"`
RetryPeriod string `yaml:"retry-period"` RetryPeriod string `yaml:"retry-period"`
@ -68,9 +75,28 @@ type LogEntry struct {
} }
func (c *Conf) setup() { func (c *Conf) setup() {
for patternName, pattern := range c.Patterns {
c.Patterns[patternName] = fmt.Sprintf("(?P<%s>%s)", patternName, pattern) for patternName := range c.Patterns {
pattern := c.Patterns[patternName]
pattern.name = patternName
pattern.nameWithBraces = fmt.Sprintf("<%s>", pattern.name)
if pattern.Regex == "" {
log.Fatalf("FATAL Bad configuration: pattern's regex %v is empty!", patternName)
} }
compiled, err := regexp.Compile(fmt.Sprintf("^%v$", pattern.Regex))
if err != nil {
log.Fatalf("FATAL Bad configuration: pattern %v doesn't compile!", patternName)
}
c.Patterns[patternName].Regex = fmt.Sprintf("(?P<%s>%s)", patternName, pattern.Regex)
for _, ignore := range pattern.Ignore {
if !compiled.MatchString(ignore) {
log.Fatalf("FATAL Bad configuration: pattern ignore '%v' doesn't match pattern %v! It should be fixed or removed.", ignore, pattern.nameWithBraces)
}
}
}
if len(c.Streams) == 0 { if len(c.Streams) == 0 {
log.Fatalln("FATAL Bad configuration: no streams configured!") log.Fatalln("FATAL Bad configuration: no streams configured!")
} }
@ -109,24 +135,24 @@ func (c *Conf) setup() {
// Look for Patterns inside Regexes // Look for Patterns inside Regexes
for _, regex := range filter.Regex { for _, regex := range filter.Regex {
for patternName, pattern := range c.Patterns { for patternName, pattern := range c.Patterns {
if strings.Contains(regex, patternName) { if strings.Contains(regex, pattern.nameWithBraces) {
switch filter.patternName { if filter.pattern == nil {
case "": filter.pattern = pattern
filter.patternName = patternName } else if filter.pattern == pattern {
filter.patternWithBraces = fmt.Sprintf("<%s>", patternName)
case patternName:
// no op // no op
default: } else {
log.Fatalf( log.Fatalf(
"Bad configuration: Can't mix different patterns (%s, %s) in same filter (%s.%s)\n", "Bad configuration: Can't mix different patterns (%s, %s) in same filter (%s.%s)\n",
filter.patternName, patternName, streamName, filterName, filter.pattern.name, patternName, streamName, filterName,
) )
} }
regex = strings.Replace(regex, fmt.Sprintf("<%s>", patternName), pattern, 1) // FIXME should go in the `if filter.pattern == nil`?
regex = strings.Replace(regex, pattern.nameWithBraces, pattern.Regex, 1)
} }
} }
// TODO regexp.Compile and show proper message if it doesn't instead of panicing
filter.compiledRegex = append(filter.compiledRegex, *regexp.MustCompile(regex)) filter.compiledRegex = append(filter.compiledRegex, *regexp.MustCompile(regex))
} }

View File

@ -1,20 +1,19 @@
--- ---
patterns: patterns:
ip: '(([0-9]{1,3}\.){3}[0-9]{1,3})|([0-9a-fA-F:]{2,90})' ip:
regex: '(?:(?:[0-9]{1,3}\.){3}[0-9]{1,3})|(?:[0-9a-fA-F:]{2,90})'
ignore:
- 1.0.0.1
streams: streams:
tailDown: tailDown:
cmd: [ "sh", "-c", "echo 'found 1.1.1.1' && sleep 2s && echo 'found 1.1.1.2' && sleep 2s && echo 'found 1.1.1.1' && sleep 10m" ] cmd: [ "sh", "-c", "echo 'found 1.1.1.1' && sleep 2 && echo 'found 1.0.0.1' && sleep 10m" ]
filters: filters:
findIP: findIP:
regex: regex:
- found <ip> - '^found <ip>'
retry: 2 retry: 2
retry-period: 1m retry-period: 1m
actions: actions:
damn: damn:
cmd: [ "echo", "<ip>" ] cmd: [ "echo", "<ip>" ]
sleepdamn:
cmd: [ "echo", "sleep", "<ip>" ]
after: 8m
onexit: true

View File

@ -8,7 +8,11 @@ definitions:
# patterns are substitued in regexes. # patterns are substitued in regexes.
# when a filter performs an action, it replaces the found pattern # when a filter performs an action, it replaces the found pattern
patterns: patterns:
ip: '(([0-9]{1,3}\.){3}[0-9]{1,3})|([0-9a-fA-F:]{2,90})' ip:
regex: '(?:(?:[0-9]{1,3}\.){3}[0-9]{1,3})|(?:[0-9a-fA-F:]{2,90})'
ignore:
- 127.0.0.1
- ::1
# streams are command that are run # streams are command that are run
# their output will be used by one or more filters # their output will be used by one or more filters