Allow grok to produce metrics with no fields (#5533)

This commit is contained in:
Daniel Nelson 2019-03-05 11:07:39 -08:00 committed by GitHub
parent 1dcfecdb59
commit a0527db037
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 40 deletions

View File

@ -11,10 +11,9 @@ import (
"strings" "strings"
"time" "time"
"github.com/vjeantet/grok"
"github.com/influxdata/telegraf" "github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/metric" "github.com/influxdata/telegraf/metric"
"github.com/vjeantet/grok"
) )
var timeLayouts = map[string]string{ var timeLayouts = map[string]string{
@ -361,10 +360,6 @@ func (p *Parser) ParseLine(line string) (telegraf.Metric, error) {
} }
} }
if len(fields) == 0 {
return nil, fmt.Errorf("grok: must have one or more fields")
}
if p.UniqueTimestamp != "auto" { if p.UniqueTimestamp != "auto" {
return metric.New(p.Measurement, tags, fields, timestamp) return metric.New(p.Measurement, tags, fields, timestamp)
} }

View File

@ -5,6 +5,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/influxdata/telegraf/testutil"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -571,61 +572,81 @@ func TestCompileErrors(t *testing.T) {
assert.Error(t, p.Compile()) assert.Error(t, p.Compile())
} }
func TestParseErrors(t *testing.T) { func TestParseErrors_MissingPattern(t *testing.T) {
// Parse fails because the pattern doesn't exist
p := &Parser{ p := &Parser{
Patterns: []string{"%{TEST_LOG_B}"}, Measurement: "grok",
Patterns: []string{"%{TEST_LOG_B}"},
CustomPatterns: ` CustomPatterns: `
TEST_LOG_A %{HTTPDATE:ts:ts-httpd} %{WORD:myword:int} %{} TEST_LOG_A %{HTTPDATE:ts:ts-httpd} %{WORD:myword:int} %{}
`, `,
} }
assert.Error(t, p.Compile()) require.Error(t, p.Compile())
_, err := p.ParseLine(`[04/Jun/2016:12:41:45 +0100] notnumber 200 192.168.1.1 5.432µs 101`) _, err := p.ParseLine(`[04/Jun/2016:12:41:45 +0100] notnumber 200 192.168.1.1 5.432µs 101`)
assert.Error(t, err) require.Error(t, err)
}
// Parse fails because myword is not an int func TestParseErrors_WrongIntegerType(t *testing.T) {
p = &Parser{ p := &Parser{
Patterns: []string{"%{TEST_LOG_A}"}, Measurement: "grok",
Patterns: []string{"%{TEST_LOG_A}"},
CustomPatterns: ` CustomPatterns: `
TEST_LOG_A %{HTTPDATE:ts:ts-httpd} %{WORD:myword:int} TEST_LOG_A %{NUMBER:ts:ts-epoch} %{WORD:myword:int}
`, `,
} }
assert.NoError(t, p.Compile()) require.NoError(t, p.Compile())
_, err = p.ParseLine(`04/Jun/2016:12:41:45 +0100 notnumber`) m, err := p.ParseLine(`0 notnumber`)
assert.Error(t, err) require.NoError(t, err)
testutil.RequireMetricEqual(t,
m,
testutil.MustMetric("grok", map[string]string{}, map[string]interface{}{}, time.Unix(0, 0)))
}
// Parse fails because myword is not a float func TestParseErrors_WrongFloatType(t *testing.T) {
p = &Parser{ p := &Parser{
Patterns: []string{"%{TEST_LOG_A}"}, Measurement: "grok",
Patterns: []string{"%{TEST_LOG_A}"},
CustomPatterns: ` CustomPatterns: `
TEST_LOG_A %{HTTPDATE:ts:ts-httpd} %{WORD:myword:float} TEST_LOG_A %{NUMBER:ts:ts-epoch} %{WORD:myword:float}
`, `,
} }
assert.NoError(t, p.Compile()) require.NoError(t, p.Compile())
_, err = p.ParseLine(`04/Jun/2016:12:41:45 +0100 notnumber`) m, err := p.ParseLine(`0 notnumber`)
assert.Error(t, err) require.NoError(t, err)
testutil.RequireMetricEqual(t,
m,
testutil.MustMetric("grok", map[string]string{}, map[string]interface{}{}, time.Unix(0, 0)))
}
// Parse fails because myword is not a duration func TestParseErrors_WrongDurationType(t *testing.T) {
p = &Parser{ p := &Parser{
Patterns: []string{"%{TEST_LOG_A}"}, Measurement: "grok",
Patterns: []string{"%{TEST_LOG_A}"},
CustomPatterns: ` CustomPatterns: `
TEST_LOG_A %{HTTPDATE:ts:ts-httpd} %{WORD:myword:duration} TEST_LOG_A %{NUMBER:ts:ts-epoch} %{WORD:myword:duration}
`, `,
} }
assert.NoError(t, p.Compile()) require.NoError(t, p.Compile())
_, err = p.ParseLine(`04/Jun/2016:12:41:45 +0100 notnumber`) m, err := p.ParseLine(`0 notnumber`)
assert.Error(t, err) require.NoError(t, err)
testutil.RequireMetricEqual(t,
m,
testutil.MustMetric("grok", map[string]string{}, map[string]interface{}{}, time.Unix(0, 0)))
}
// Parse fails because the time layout is wrong. func TestParseErrors_WrongTimeLayout(t *testing.T) {
p = &Parser{ p := &Parser{
Patterns: []string{"%{TEST_LOG_A}"}, Measurement: "grok",
Patterns: []string{"%{TEST_LOG_A}"},
CustomPatterns: ` CustomPatterns: `
TEST_LOG_A %{HTTPDATE:ts:ts-unix} %{WORD:myword:duration} TEST_LOG_A %{NUMBER:ts:ts-epoch} %{WORD:myword:duration}
`, `,
} }
assert.NoError(t, p.Compile()) require.NoError(t, p.Compile())
_, err = p.ParseLine(`04/Jun/2016:12:41:45 +0100 notnumber`) m, err := p.ParseLine(`0 notnumber`)
assert.Error(t, err) require.NoError(t, err)
testutil.RequireMetricEqual(t,
m,
testutil.MustMetric("grok", map[string]string{}, map[string]interface{}{}, time.Unix(0, 0)))
} }
func TestTsModder(t *testing.T) { func TestTsModder(t *testing.T) {

View File

@ -298,7 +298,6 @@ func newJSONParser(
return parser return parser
} }
//Deprecated: Use NewParser to get a JSONParser object
func newGrokParser(metricName string, func newGrokParser(metricName string,
patterns []string, nPatterns []string, patterns []string, nPatterns []string,
cPatterns string, cPatternFiles []string, cPatterns string, cPatternFiles []string,