Skip to content

Commit

Permalink
Allow grok to produce metrics with no fields (influxdata#5533)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielnelson authored Mar 5, 2019
1 parent 1dcfecd commit a0527db
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 40 deletions.
7 changes: 1 addition & 6 deletions plugins/parsers/grok/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down Expand Up @@ -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)
}
Expand Down
87 changes: 54 additions & 33 deletions plugins/parsers/grok/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"testing"
"time"

"github.com/influxdata/telegraf/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -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{
Patterns: []string{"%{TEST_LOG_B}"},
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{
Patterns: []string{"%{TEST_LOG_A}"},
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{
Patterns: []string{"%{TEST_LOG_A}"},
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{
Patterns: []string{"%{TEST_LOG_A}"},
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{
Patterns: []string{"%{TEST_LOG_A}"},
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) {
Expand Down
1 change: 0 additions & 1 deletion plugins/parsers/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit a0527db

Please sign in to comment.