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,16 +42,27 @@ func cmdStdout(commandline []string) chan *string {
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
func (f *Filter) match(line *string) string {
for _, regex := range f.compiledRegex {
if matches := regex.FindStringSubmatch(*line); matches != nil {
match := matches[regex.SubexpIndex(f.patternName)]
match := matches[regex.SubexpIndex(f.pattern.name)]
log.Printf("INFO %s.%s: match [%v]\n", f.stream.name, f.name, match)
return match
if f.pattern.notAnIgnore(&match) {
log.Printf("INFO %s.%s: match [%v]\n", f.stream.name, f.name, match)
return match
}
}
}
return ""
@ -94,7 +105,7 @@ func (a *Action) exec(match string, advance time.Duration) {
if doExec {
computedCommand := make([]string, 0, len(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)

View File

@ -15,8 +15,16 @@ import (
)
type Conf struct {
Patterns map[string]string `yaml:"patterns"`
Streams map[string]*Stream `yaml:"streams"`
Patterns map[string]*Pattern `yaml:"patterns"`
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.
@ -33,10 +41,9 @@ type Filter struct {
stream *Stream `yaml:"-"`
name string `yaml:"-"`
Regex []string `yaml:"regex"`
compiledRegex []regexp.Regexp `yaml:"-"`
patternName string `yaml:"-"`
patternWithBraces string `yaml:"-"`
Regex []string `yaml:"regex"`
compiledRegex []regexp.Regexp `yaml:"-"`
pattern *Pattern `yaml:"-"`
Retry int `yaml:"retry"`
RetryPeriod string `yaml:"retry-period"`
@ -68,9 +75,28 @@ type LogEntry struct {
}
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 {
log.Fatalln("FATAL Bad configuration: no streams configured!")
}
@ -109,24 +135,24 @@ func (c *Conf) setup() {
// Look for Patterns inside Regexes
for _, regex := range filter.Regex {
for patternName, pattern := range c.Patterns {
if strings.Contains(regex, patternName) {
if strings.Contains(regex, pattern.nameWithBraces) {
switch filter.patternName {
case "":
filter.patternName = patternName
filter.patternWithBraces = fmt.Sprintf("<%s>", patternName)
case patternName:
if filter.pattern == nil {
filter.pattern = pattern
} else if filter.pattern == pattern {
// no op
default:
} else {
log.Fatalf(
"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))
}

View File

@ -1,20 +1,19 @@
---
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:
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:
findIP:
regex:
- found <ip>
- '^found <ip>'
retry: 2
retry-period: 1m
actions:
damn:
cmd: [ "echo", "<ip>" ]
sleepdamn:
cmd: [ "echo", "sleep", "<ip>" ]
after: 8m
onexit: true

View File

@ -8,7 +8,11 @@ definitions:
# patterns are substitued in regexes.
# when a filter performs an action, it replaces the found pattern
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
# their output will be used by one or more filters