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"
"time"
"github.com/vjeantet/grok"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/metric"
"github.com/vjeantet/grok"
)
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" {
return metric.New(p.Measurement, tags, fields, timestamp)
}

View File

@ -5,6 +5,7 @@ import (
"testing"
"time"
"github.com/influxdata/telegraf/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -571,61 +572,81 @@ func TestCompileErrors(t *testing.T) {
assert.Error(t, p.Compile())
}
func TestParseErrors(t *testing.T) {
// Parse fails because the pattern doesn't exist
func TestParseErrors_MissingPattern(t *testing.T) {
p := &Parser{
Measurement: "grok",
Patterns: []string{"%{TEST_LOG_B}"},
CustomPatterns: `
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`)
assert.Error(t, err)
require.Error(t, err)
}
// Parse fails because myword is not an int
p = &Parser{
func TestParseErrors_WrongIntegerType(t *testing.T) {
p := &Parser{
Measurement: "grok",
Patterns: []string{"%{TEST_LOG_A}"},
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())
_, err = p.ParseLine(`04/Jun/2016:12:41:45 +0100 notnumber`)
assert.Error(t, err)
require.NoError(t, p.Compile())
m, err := p.ParseLine(`0 notnumber`)
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
p = &Parser{
func TestParseErrors_WrongFloatType(t *testing.T) {
p := &Parser{
Measurement: "grok",
Patterns: []string{"%{TEST_LOG_A}"},
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())
_, err = p.ParseLine(`04/Jun/2016:12:41:45 +0100 notnumber`)
assert.Error(t, err)
require.NoError(t, p.Compile())
m, err := p.ParseLine(`0 notnumber`)
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
p = &Parser{
func TestParseErrors_WrongDurationType(t *testing.T) {
p := &Parser{
Measurement: "grok",
Patterns: []string{"%{TEST_LOG_A}"},
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())
_, err = p.ParseLine(`04/Jun/2016:12:41:45 +0100 notnumber`)
assert.Error(t, err)
require.NoError(t, p.Compile())
m, err := p.ParseLine(`0 notnumber`)
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.
p = &Parser{
func TestParseErrors_WrongTimeLayout(t *testing.T) {
p := &Parser{
Measurement: "grok",
Patterns: []string{"%{TEST_LOG_A}"},
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())
_, err = p.ParseLine(`04/Jun/2016:12:41:45 +0100 notnumber`)
assert.Error(t, err)
require.NoError(t, p.Compile())
m, err := p.ParseLine(`0 notnumber`)
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) {

View File

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