From 6bbed7aa906828cca31d262da6721943e21d56fa Mon Sep 17 00:00:00 2001 From: Daniel Nelson Date: Fri, 16 Jun 2017 13:16:48 -0700 Subject: [PATCH] Allow dos line endings in tail and logparser (#2920) Parsing dos line ending delimited line protocol is still illegal in most cases. --- plugins/inputs/logparser/logparser.go | 18 +++++++++------- plugins/inputs/tail/tail.go | 6 +++++- plugins/inputs/tail/tail_test.go | 30 +++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/plugins/inputs/logparser/logparser.go b/plugins/inputs/logparser/logparser.go index 6fee34b61..ea1e5d641 100644 --- a/plugins/inputs/logparser/logparser.go +++ b/plugins/inputs/logparser/logparser.go @@ -4,6 +4,7 @@ import ( "fmt" "log" "reflect" + "strings" "sync" "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/apache.log -> only tail the apache log file files = ["/var/log/apache/access.log"] - + ## Read files that currently exist from the beginning. Files that are created ## while telegraf is running (and that match the "files" globs) will always ## be read from the beginning. @@ -63,17 +64,17 @@ const sampleConfig = ` ## %{COMMON_LOG_FORMAT} (plain apache & nginx access logs) ## %{COMBINED_LOG_FORMAT} (access logs + referrer & agent) patterns = ["%{COMBINED_LOG_FORMAT}"] - + ## Name of the outputted measurement name. measurement = "apache_access_log" - + ## Full path(s) to custom pattern files. custom_pattern_files = [] - + ## Custom patterns can also be defined here. Put one pattern per line. 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 ## 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 } + // Fix up files with Windows line endings. + text := strings.TrimRight(line.Text, "\r") + select { case <-l.done: - case l.lines <- line.Text: + case l.lines <- text: } } } diff --git a/plugins/inputs/tail/tail.go b/plugins/inputs/tail/tail.go index e360dcb64..05a1c95af 100644 --- a/plugins/inputs/tail/tail.go +++ b/plugins/inputs/tail/tail.go @@ -2,6 +2,7 @@ package tail import ( "fmt" + "strings" "sync" "github.com/influxdata/tail" @@ -123,7 +124,10 @@ func (t *Tail) receiver(tailer *tail.Tail) { tailer.Filename, err)) 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 { t.acc.AddFields(m.Name(), m.Fields(), m.Tags(), m.Time()) } else { diff --git a/plugins/inputs/tail/tail_test.go b/plugins/inputs/tail/tail_test.go index 9e3888a1d..34e2abce9 100644 --- a/plugins/inputs/tail/tail_test.go +++ b/plugins/inputs/tail/tail_test.go @@ -103,3 +103,33 @@ func TestTailBadLine(t *testing.T) { acc.WaitError(1) 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), + }) +}