Allow grok to produce metrics with no fields (#5533)
This commit is contained in:
parent
1dcfecdb59
commit
a0527db037
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue