Allow dos line endings in tail and logparser (#2920)

Parsing dos line ending delimited line protocol is still illegal in most
cases.
This commit is contained in:
Daniel Nelson 2017-06-16 13:16:48 -07:00 committed by GitHub
parent 148f81682a
commit 6bbed7aa90
3 changed files with 46 additions and 8 deletions

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"log" "log"
"reflect" "reflect"
"strings"
"sync" "sync"
"github.com/influxdata/tail" "github.com/influxdata/tail"
@ -47,7 +48,7 @@ const sampleConfig = `
## /var/log/*/*.log -> find all .log files with a parent dir in /var/log ## /var/log/*/*.log -> find all .log files with a parent dir in /var/log
## /var/log/apache.log -> only tail the apache log file ## /var/log/apache.log -> only tail the apache log file
files = ["/var/log/apache/access.log"] files = ["/var/log/apache/access.log"]
## Read files that currently exist from the beginning. Files that are created ## Read files that currently exist from the beginning. Files that are created
## while telegraf is running (and that match the "files" globs) will always ## while telegraf is running (and that match the "files" globs) will always
## be read from the beginning. ## be read from the beginning.
@ -63,17 +64,17 @@ const sampleConfig = `
## %{COMMON_LOG_FORMAT} (plain apache & nginx access logs) ## %{COMMON_LOG_FORMAT} (plain apache & nginx access logs)
## %{COMBINED_LOG_FORMAT} (access logs + referrer & agent) ## %{COMBINED_LOG_FORMAT} (access logs + referrer & agent)
patterns = ["%{COMBINED_LOG_FORMAT}"] patterns = ["%{COMBINED_LOG_FORMAT}"]
## Name of the outputted measurement name. ## Name of the outputted measurement name.
measurement = "apache_access_log" measurement = "apache_access_log"
## Full path(s) to custom pattern files. ## Full path(s) to custom pattern files.
custom_pattern_files = [] custom_pattern_files = []
## Custom patterns can also be defined here. Put one pattern per line. ## Custom patterns can also be defined here. Put one pattern per line.
custom_patterns = ''' custom_patterns = '''
## Timezone allows you to provide an override for timestamps that ## Timezone allows you to provide an override for timestamps that
## don't already include an offset ## don't already include an offset
## e.g. 04/06/2016 12:41:45 data one two 5.43µs ## e.g. 04/06/2016 12:41:45 data one two 5.43µs
## ##
@ -207,9 +208,12 @@ func (l *LogParserPlugin) receiver(tailer *tail.Tail) {
continue continue
} }
// Fix up files with Windows line endings.
text := strings.TrimRight(line.Text, "\r")
select { select {
case <-l.done: case <-l.done:
case l.lines <- line.Text: case l.lines <- text:
} }
} }
} }

View File

@ -2,6 +2,7 @@ package tail
import ( import (
"fmt" "fmt"
"strings"
"sync" "sync"
"github.com/influxdata/tail" "github.com/influxdata/tail"
@ -123,7 +124,10 @@ func (t *Tail) receiver(tailer *tail.Tail) {
tailer.Filename, err)) tailer.Filename, err))
continue continue
} }
m, err = t.parser.ParseLine(line.Text) // Fix up files with Windows line endings.
text := strings.TrimRight(line.Text, "\r")
m, err = t.parser.ParseLine(text)
if err == nil { if err == nil {
t.acc.AddFields(m.Name(), m.Fields(), m.Tags(), m.Time()) t.acc.AddFields(m.Name(), m.Fields(), m.Tags(), m.Time())
} else { } else {

View File

@ -103,3 +103,33 @@ func TestTailBadLine(t *testing.T) {
acc.WaitError(1) acc.WaitError(1)
assert.Contains(t, acc.Errors[0].Error(), "E! Malformed log line") assert.Contains(t, acc.Errors[0].Error(), "E! Malformed log line")
} }
func TestTailDosLineendings(t *testing.T) {
tmpfile, err := ioutil.TempFile("", "")
require.NoError(t, err)
defer os.Remove(tmpfile.Name())
_, err = tmpfile.WriteString("cpu usage_idle=100\r\ncpu2 usage_idle=200\r\n")
require.NoError(t, err)
tt := NewTail()
tt.FromBeginning = true
tt.Files = []string{tmpfile.Name()}
p, _ := parsers.NewInfluxParser()
tt.SetParser(p)
defer tt.Stop()
defer tmpfile.Close()
acc := testutil.Accumulator{}
require.NoError(t, tt.Start(&acc))
require.NoError(t, acc.GatherError(tt.Gather))
acc.Wait(2)
acc.AssertContainsFields(t, "cpu",
map[string]interface{}{
"usage_idle": float64(100),
})
acc.AssertContainsFields(t, "cpu2",
map[string]interface{}{
"usage_idle": float64(200),
})
}