Fix cleanup of csv parser options, use per file parser (#4712)

This commit is contained in:
Daniel Nelson
2018-09-18 09:23:45 -07:00
committed by GitHub
parent 1d76343422
commit b5299f4cc4
7 changed files with 160 additions and 53 deletions

View File

@@ -191,15 +191,13 @@ func (l *LogParserPlugin) tailNewfiles(fromBeginning bool) error {
Poll: poll,
Logger: tail.DiscardingLogger,
})
//add message saying a new tailer was added for the file
log.Printf("D! tail added for file: %v", file)
if err != nil {
l.acc.AddError(err)
continue
}
log.Printf("D! [inputs.logparser] tail added for file: %v", file)
// create a goroutine for each "tailer"
l.wg.Add(1)
go l.receiver(tailer)

View File

@@ -4,6 +4,7 @@ package tail
import (
"fmt"
"log"
"strings"
"sync"
@@ -25,10 +26,10 @@ type Tail struct {
Pipe bool
WatchMethod string
tailers map[string]*tail.Tail
parser parsers.Parser
wg sync.WaitGroup
acc telegraf.Accumulator
tailers map[string]*tail.Tail
parserFunc parsers.ParserFunc
wg sync.WaitGroup
acc telegraf.Accumulator
sync.Mutex
}
@@ -130,10 +131,18 @@ func (t *Tail) tailNewFiles(fromBeginning bool) error {
t.acc.AddError(err)
continue
}
log.Printf("D! [inputs.tail] tail added for file: %v", file)
parser, err := t.parserFunc()
if err != nil {
t.acc.AddError(fmt.Errorf("error creating parser: %v", err))
}
// create a goroutine for each "tailer"
t.wg.Add(1)
go t.receiver(tailer)
t.tailers[file] = tailer
go t.receiver(parser, tailer)
t.tailers[tailer.Filename] = tailer
}
}
return nil
@@ -141,9 +150,11 @@ func (t *Tail) tailNewFiles(fromBeginning bool) error {
// this is launched as a goroutine to continuously watch a tailed logfile
// for changes, parse any incoming msgs, and add to the accumulator.
func (t *Tail) receiver(tailer *tail.Tail) {
func (t *Tail) receiver(parser parsers.Parser, tailer *tail.Tail) {
defer t.wg.Done()
var firstLine = true
var metrics []telegraf.Metric
var m telegraf.Metric
var err error
var line *tail.Line
@@ -156,7 +167,21 @@ func (t *Tail) receiver(tailer *tail.Tail) {
// Fix up files with Windows line endings.
text := strings.TrimRight(line.Text, "\r")
m, err = t.parser.ParseLine(text)
if firstLine {
metrics, err = parser.Parse([]byte(text))
if err == nil {
if len(metrics) == 0 {
firstLine = false
continue
} else {
m = metrics[0]
}
}
firstLine = false
} else {
m, err = parser.ParseLine(text)
}
if err == nil {
if m != nil {
tags := m.Tags()
@@ -168,6 +193,9 @@ func (t *Tail) receiver(tailer *tail.Tail) {
tailer.Filename, line.Text, err))
}
}
log.Printf("D! [inputs.tail] tail removed for file: %v", tailer.Filename)
if err := tailer.Err(); err != nil {
t.acc.AddError(fmt.Errorf("E! Error tailing file %s, Error: %s\n",
tailer.Filename, err))
@@ -183,13 +211,16 @@ func (t *Tail) Stop() {
if err != nil {
t.acc.AddError(fmt.Errorf("E! Error stopping tail on file %s\n", tailer.Filename))
}
}
for _, tailer := range t.tailers {
tailer.Cleanup()
}
t.wg.Wait()
}
func (t *Tail) SetParser(parser parsers.Parser) {
t.parser = parser
func (t *Tail) SetParserFunc(fn parsers.ParserFunc) {
t.parserFunc = fn
}
func init() {

View File

@@ -27,8 +27,7 @@ func TestTailFromBeginning(t *testing.T) {
tt := NewTail()
tt.FromBeginning = true
tt.Files = []string{tmpfile.Name()}
p, _ := parsers.NewInfluxParser()
tt.SetParser(p)
tt.SetParserFunc(parsers.NewInfluxParser)
defer tt.Stop()
defer tmpfile.Close()
@@ -60,8 +59,7 @@ func TestTailFromEnd(t *testing.T) {
tt := NewTail()
tt.Files = []string{tmpfile.Name()}
p, _ := parsers.NewInfluxParser()
tt.SetParser(p)
tt.SetParserFunc(parsers.NewInfluxParser)
defer tt.Stop()
defer tmpfile.Close()
@@ -98,8 +96,7 @@ func TestTailBadLine(t *testing.T) {
tt := NewTail()
tt.FromBeginning = true
tt.Files = []string{tmpfile.Name()}
p, _ := parsers.NewInfluxParser()
tt.SetParser(p)
tt.SetParserFunc(parsers.NewInfluxParser)
defer tt.Stop()
defer tmpfile.Close()
@@ -124,8 +121,7 @@ func TestTailDosLineendings(t *testing.T) {
tt := NewTail()
tt.FromBeginning = true
tt.Files = []string{tmpfile.Name()}
p, _ := parsers.NewInfluxParser()
tt.SetParser(p)
tt.SetParserFunc(parsers.NewInfluxParser)
defer tt.Stop()
defer tmpfile.Close()