this log format is likely soon going to be removed from a future influxdb release, so we should not be recommending that users base any of their log parsing infra on this.
588 lines
18 KiB
Go
588 lines
18 KiB
Go
package grok
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/influxdata/telegraf"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
var benchM telegraf.Metric
|
|
|
|
func Benchmark_ParseLine_CommonLogFormat(b *testing.B) {
|
|
p := &Parser{
|
|
Patterns: []string{"%{COMMON_LOG_FORMAT}"},
|
|
}
|
|
p.Compile()
|
|
|
|
var m telegraf.Metric
|
|
for n := 0; n < b.N; n++ {
|
|
m, _ = p.ParseLine(`127.0.0.1 user-identifier frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326`)
|
|
}
|
|
benchM = m
|
|
}
|
|
|
|
func Benchmark_ParseLine_CombinedLogFormat(b *testing.B) {
|
|
p := &Parser{
|
|
Patterns: []string{"%{COMBINED_LOG_FORMAT}"},
|
|
}
|
|
p.Compile()
|
|
|
|
var m telegraf.Metric
|
|
for n := 0; n < b.N; n++ {
|
|
m, _ = p.ParseLine(`127.0.0.1 user-identifier frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "-" "Mozilla"`)
|
|
}
|
|
benchM = m
|
|
}
|
|
|
|
func Benchmark_ParseLine_CustomPattern(b *testing.B) {
|
|
p := &Parser{
|
|
Patterns: []string{"%{TEST_LOG_A}", "%{TEST_LOG_B}"},
|
|
CustomPatterns: `
|
|
DURATION %{NUMBER}[nuµm]?s
|
|
RESPONSE_CODE %{NUMBER:response_code:tag}
|
|
RESPONSE_TIME %{DURATION:response_time:duration}
|
|
TEST_LOG_A %{NUMBER:myfloat:float} %{RESPONSE_CODE} %{IPORHOST:clientip} %{RESPONSE_TIME}
|
|
`,
|
|
}
|
|
p.Compile()
|
|
|
|
var m telegraf.Metric
|
|
for n := 0; n < b.N; n++ {
|
|
m, _ = p.ParseLine(`[04/Jun/2016:12:41:45 +0100] 1.25 200 192.168.1.1 5.432µs 101`)
|
|
}
|
|
benchM = m
|
|
}
|
|
|
|
func TestMeasurementName(t *testing.T) {
|
|
p := &Parser{
|
|
Measurement: "my_web_log",
|
|
Patterns: []string{"%{COMMON_LOG_FORMAT}"},
|
|
}
|
|
assert.NoError(t, p.Compile())
|
|
|
|
// Parse an influxdb POST request
|
|
m, err := p.ParseLine(`127.0.0.1 user-identifier frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326`)
|
|
require.NotNil(t, m)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t,
|
|
map[string]interface{}{
|
|
"resp_bytes": int64(2326),
|
|
"auth": "frank",
|
|
"client_ip": "127.0.0.1",
|
|
"http_version": float64(1.0),
|
|
"ident": "user-identifier",
|
|
"request": "/apache_pb.gif",
|
|
},
|
|
m.Fields())
|
|
assert.Equal(t, map[string]string{"verb": "GET", "resp_code": "200"}, m.Tags())
|
|
assert.Equal(t, "my_web_log", m.Name())
|
|
}
|
|
|
|
func TestCustomInfluxdbHttpd(t *testing.T) {
|
|
p := &Parser{
|
|
Patterns: []string{`\[httpd\] %{COMBINED_LOG_FORMAT} %{UUID:uuid:drop} %{NUMBER:response_time_us:int}`},
|
|
}
|
|
assert.NoError(t, p.Compile())
|
|
|
|
// Parse an influxdb POST request
|
|
m, err := p.ParseLine(`[httpd] ::1 - - [14/Jun/2016:11:33:29 +0100] "POST /write?consistency=any&db=telegraf&precision=ns&rp= HTTP/1.1" 204 0 "-" "InfluxDBClient" 6f61bc44-321b-11e6-8050-000000000000 2513`)
|
|
require.NotNil(t, m)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t,
|
|
map[string]interface{}{
|
|
"resp_bytes": int64(0),
|
|
"auth": "-",
|
|
"client_ip": "::1",
|
|
"http_version": float64(1.1),
|
|
"ident": "-",
|
|
"referrer": "-",
|
|
"request": "/write?consistency=any&db=telegraf&precision=ns&rp=",
|
|
"response_time_us": int64(2513),
|
|
"agent": "InfluxDBClient",
|
|
},
|
|
m.Fields())
|
|
assert.Equal(t, map[string]string{"verb": "POST", "resp_code": "204"}, m.Tags())
|
|
|
|
// Parse an influxdb GET request
|
|
m, err = p.ParseLine(`[httpd] ::1 - - [14/Jun/2016:12:10:02 +0100] "GET /query?db=telegraf&q=SELECT+bytes%2Cresponse_time_us+FROM+logparser_grok+WHERE+http_method+%3D+%27GET%27+AND+response_time_us+%3E+0+AND+time+%3E+now%28%29+-+1h HTTP/1.1" 200 578 "http://localhost:8083/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36" 8a3806f1-3220-11e6-8006-000000000000 988`)
|
|
require.NotNil(t, m)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t,
|
|
map[string]interface{}{
|
|
"resp_bytes": int64(578),
|
|
"auth": "-",
|
|
"client_ip": "::1",
|
|
"http_version": float64(1.1),
|
|
"ident": "-",
|
|
"referrer": "http://localhost:8083/",
|
|
"request": "/query?db=telegraf&q=SELECT+bytes%2Cresponse_time_us+FROM+logparser_grok+WHERE+http_method+%3D+%27GET%27+AND+response_time_us+%3E+0+AND+time+%3E+now%28%29+-+1h",
|
|
"response_time_us": int64(988),
|
|
"agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36",
|
|
},
|
|
m.Fields())
|
|
assert.Equal(t, map[string]string{"verb": "GET", "resp_code": "200"}, m.Tags())
|
|
}
|
|
|
|
// common log format
|
|
// 127.0.0.1 user-identifier frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326
|
|
func TestBuiltinCommonLogFormat(t *testing.T) {
|
|
p := &Parser{
|
|
Patterns: []string{"%{COMMON_LOG_FORMAT}"},
|
|
}
|
|
assert.NoError(t, p.Compile())
|
|
|
|
// Parse an influxdb POST request
|
|
m, err := p.ParseLine(`127.0.0.1 user-identifier frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326`)
|
|
require.NotNil(t, m)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t,
|
|
map[string]interface{}{
|
|
"resp_bytes": int64(2326),
|
|
"auth": "frank",
|
|
"client_ip": "127.0.0.1",
|
|
"http_version": float64(1.0),
|
|
"ident": "user-identifier",
|
|
"request": "/apache_pb.gif",
|
|
},
|
|
m.Fields())
|
|
assert.Equal(t, map[string]string{"verb": "GET", "resp_code": "200"}, m.Tags())
|
|
}
|
|
|
|
// combined log format
|
|
// 127.0.0.1 user-identifier frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "-" "Mozilla"
|
|
func TestBuiltinCombinedLogFormat(t *testing.T) {
|
|
p := &Parser{
|
|
Patterns: []string{"%{COMBINED_LOG_FORMAT}"},
|
|
}
|
|
assert.NoError(t, p.Compile())
|
|
|
|
// Parse an influxdb POST request
|
|
m, err := p.ParseLine(`127.0.0.1 user-identifier frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "-" "Mozilla"`)
|
|
require.NotNil(t, m)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t,
|
|
map[string]interface{}{
|
|
"resp_bytes": int64(2326),
|
|
"auth": "frank",
|
|
"client_ip": "127.0.0.1",
|
|
"http_version": float64(1.0),
|
|
"ident": "user-identifier",
|
|
"request": "/apache_pb.gif",
|
|
"referrer": "-",
|
|
"agent": "Mozilla",
|
|
},
|
|
m.Fields())
|
|
assert.Equal(t, map[string]string{"verb": "GET", "resp_code": "200"}, m.Tags())
|
|
}
|
|
|
|
func TestCompileStringAndParse(t *testing.T) {
|
|
p := &Parser{
|
|
Patterns: []string{"%{TEST_LOG_A}"},
|
|
CustomPatterns: `
|
|
DURATION %{NUMBER}[nuµm]?s
|
|
RESPONSE_CODE %{NUMBER:response_code:tag}
|
|
RESPONSE_TIME %{DURATION:response_time:duration}
|
|
TEST_LOG_A %{NUMBER:myfloat:float} %{RESPONSE_CODE} %{IPORHOST:clientip} %{RESPONSE_TIME}
|
|
`,
|
|
}
|
|
assert.NoError(t, p.Compile())
|
|
|
|
metricA, err := p.ParseLine(`1.25 200 192.168.1.1 5.432µs`)
|
|
require.NotNil(t, metricA)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t,
|
|
map[string]interface{}{
|
|
"clientip": "192.168.1.1",
|
|
"myfloat": float64(1.25),
|
|
"response_time": int64(5432),
|
|
},
|
|
metricA.Fields())
|
|
assert.Equal(t, map[string]string{"response_code": "200"}, metricA.Tags())
|
|
}
|
|
|
|
func TestCompileErrorsOnInvalidPattern(t *testing.T) {
|
|
p := &Parser{
|
|
Patterns: []string{"%{TEST_LOG_A}", "%{TEST_LOG_B}"},
|
|
CustomPatterns: `
|
|
DURATION %{NUMBER}[nuµm]?s
|
|
RESPONSE_CODE %{NUMBER:response_code:tag}
|
|
RESPONSE_TIME %{DURATION:response_time:duration}
|
|
TEST_LOG_A %{NUMBER:myfloat:float} %{RESPONSE_CODE} %{IPORHOST:clientip} %{RESPONSE_TIME}
|
|
`,
|
|
}
|
|
assert.Error(t, p.Compile())
|
|
|
|
metricA, _ := p.ParseLine(`1.25 200 192.168.1.1 5.432µs`)
|
|
require.Nil(t, metricA)
|
|
}
|
|
|
|
func TestParsePatternsWithoutCustom(t *testing.T) {
|
|
p := &Parser{
|
|
Patterns: []string{"%{POSINT:ts:ts-epochnano} response_time=%{POSINT:response_time:int} mymetric=%{NUMBER:metric:float}"},
|
|
}
|
|
assert.NoError(t, p.Compile())
|
|
|
|
metricA, err := p.ParseLine(`1466004605359052000 response_time=20821 mymetric=10890.645`)
|
|
require.NotNil(t, metricA)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t,
|
|
map[string]interface{}{
|
|
"response_time": int64(20821),
|
|
"metric": float64(10890.645),
|
|
},
|
|
metricA.Fields())
|
|
assert.Equal(t, map[string]string{}, metricA.Tags())
|
|
assert.Equal(t, time.Unix(0, 1466004605359052000), metricA.Time())
|
|
}
|
|
|
|
func TestParseEpochNano(t *testing.T) {
|
|
p := &Parser{
|
|
Patterns: []string{"%{MYAPP}"},
|
|
CustomPatterns: `
|
|
MYAPP %{POSINT:ts:ts-epochnano} response_time=%{POSINT:response_time:int} mymetric=%{NUMBER:metric:float}
|
|
`,
|
|
}
|
|
assert.NoError(t, p.Compile())
|
|
|
|
metricA, err := p.ParseLine(`1466004605359052000 response_time=20821 mymetric=10890.645`)
|
|
require.NotNil(t, metricA)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t,
|
|
map[string]interface{}{
|
|
"response_time": int64(20821),
|
|
"metric": float64(10890.645),
|
|
},
|
|
metricA.Fields())
|
|
assert.Equal(t, map[string]string{}, metricA.Tags())
|
|
assert.Equal(t, time.Unix(0, 1466004605359052000), metricA.Time())
|
|
}
|
|
|
|
func TestParseEpoch(t *testing.T) {
|
|
p := &Parser{
|
|
Patterns: []string{"%{MYAPP}"},
|
|
CustomPatterns: `
|
|
MYAPP %{POSINT:ts:ts-epoch} response_time=%{POSINT:response_time:int} mymetric=%{NUMBER:metric:float}
|
|
`,
|
|
}
|
|
assert.NoError(t, p.Compile())
|
|
|
|
metricA, err := p.ParseLine(`1466004605 response_time=20821 mymetric=10890.645`)
|
|
require.NotNil(t, metricA)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t,
|
|
map[string]interface{}{
|
|
"response_time": int64(20821),
|
|
"metric": float64(10890.645),
|
|
},
|
|
metricA.Fields())
|
|
assert.Equal(t, map[string]string{}, metricA.Tags())
|
|
assert.Equal(t, time.Unix(1466004605, 0), metricA.Time())
|
|
}
|
|
|
|
func TestParseEpochErrors(t *testing.T) {
|
|
p := &Parser{
|
|
Patterns: []string{"%{MYAPP}"},
|
|
CustomPatterns: `
|
|
MYAPP %{WORD:ts:ts-epoch} response_time=%{POSINT:response_time:int} mymetric=%{NUMBER:metric:float}
|
|
`,
|
|
}
|
|
assert.NoError(t, p.Compile())
|
|
|
|
_, err := p.ParseLine(`foobar response_time=20821 mymetric=10890.645`)
|
|
assert.NoError(t, err)
|
|
|
|
p = &Parser{
|
|
Patterns: []string{"%{MYAPP}"},
|
|
CustomPatterns: `
|
|
MYAPP %{WORD:ts:ts-epochnano} response_time=%{POSINT:response_time:int} mymetric=%{NUMBER:metric:float}
|
|
`,
|
|
}
|
|
assert.NoError(t, p.Compile())
|
|
|
|
_, err = p.ParseLine(`foobar response_time=20821 mymetric=10890.645`)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestParseGenericTimestamp(t *testing.T) {
|
|
p := &Parser{
|
|
Patterns: []string{`\[%{HTTPDATE:ts:ts}\] response_time=%{POSINT:response_time:int} mymetric=%{NUMBER:metric:float}`},
|
|
}
|
|
assert.NoError(t, p.Compile())
|
|
|
|
metricA, err := p.ParseLine(`[09/Jun/2016:03:37:03 +0000] response_time=20821 mymetric=10890.645`)
|
|
require.NotNil(t, metricA)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t,
|
|
map[string]interface{}{
|
|
"response_time": int64(20821),
|
|
"metric": float64(10890.645),
|
|
},
|
|
metricA.Fields())
|
|
assert.Equal(t, map[string]string{}, metricA.Tags())
|
|
assert.Equal(t, time.Unix(1465443423, 0).UTC(), metricA.Time().UTC())
|
|
|
|
metricB, err := p.ParseLine(`[09/Jun/2016:03:37:04 +0000] response_time=20821 mymetric=10890.645`)
|
|
require.NotNil(t, metricB)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t,
|
|
map[string]interface{}{
|
|
"response_time": int64(20821),
|
|
"metric": float64(10890.645),
|
|
},
|
|
metricB.Fields())
|
|
assert.Equal(t, map[string]string{}, metricB.Tags())
|
|
assert.Equal(t, time.Unix(1465443424, 0).UTC(), metricB.Time().UTC())
|
|
}
|
|
|
|
func TestParseGenericTimestampNotFound(t *testing.T) {
|
|
p := &Parser{
|
|
Patterns: []string{`\[%{NOTSPACE:ts:ts}\] response_time=%{POSINT:response_time:int} mymetric=%{NUMBER:metric:float}`},
|
|
}
|
|
assert.NoError(t, p.Compile())
|
|
|
|
metricA, err := p.ParseLine(`[foobar] response_time=20821 mymetric=10890.645`)
|
|
require.NotNil(t, metricA)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t,
|
|
map[string]interface{}{
|
|
"response_time": int64(20821),
|
|
"metric": float64(10890.645),
|
|
},
|
|
metricA.Fields())
|
|
assert.Equal(t, map[string]string{}, metricA.Tags())
|
|
}
|
|
|
|
func TestCompileFileAndParse(t *testing.T) {
|
|
p := &Parser{
|
|
Patterns: []string{"%{TEST_LOG_A}", "%{TEST_LOG_B}"},
|
|
CustomPatternFiles: []string{"./testdata/test-patterns"},
|
|
}
|
|
assert.NoError(t, p.Compile())
|
|
|
|
metricA, err := p.ParseLine(`[04/Jun/2016:12:41:45 +0100] 1.25 200 192.168.1.1 5.432µs 101`)
|
|
require.NotNil(t, metricA)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t,
|
|
map[string]interface{}{
|
|
"clientip": "192.168.1.1",
|
|
"myfloat": float64(1.25),
|
|
"response_time": int64(5432),
|
|
"myint": int64(101),
|
|
},
|
|
metricA.Fields())
|
|
assert.Equal(t, map[string]string{"response_code": "200"}, metricA.Tags())
|
|
assert.Equal(t,
|
|
time.Date(2016, time.June, 4, 12, 41, 45, 0, time.FixedZone("foo", 60*60)).Nanosecond(),
|
|
metricA.Time().Nanosecond())
|
|
|
|
metricB, err := p.ParseLine(`[04/06/2016--12:41:45] 1.25 mystring dropme nomodifier`)
|
|
require.NotNil(t, metricB)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t,
|
|
map[string]interface{}{
|
|
"myfloat": 1.25,
|
|
"mystring": "mystring",
|
|
"nomodifier": "nomodifier",
|
|
},
|
|
metricB.Fields())
|
|
assert.Equal(t, map[string]string{}, metricB.Tags())
|
|
assert.Equal(t,
|
|
time.Date(2016, time.June, 4, 12, 41, 45, 0, time.FixedZone("foo", 60*60)).Nanosecond(),
|
|
metricB.Time().Nanosecond())
|
|
}
|
|
|
|
func TestCompileNoModifiersAndParse(t *testing.T) {
|
|
p := &Parser{
|
|
Patterns: []string{"%{TEST_LOG_C}"},
|
|
CustomPatterns: `
|
|
DURATION %{NUMBER}[nuµm]?s
|
|
TEST_LOG_C %{NUMBER:myfloat} %{NUMBER} %{IPORHOST:clientip} %{DURATION:rt}
|
|
`,
|
|
}
|
|
assert.NoError(t, p.Compile())
|
|
|
|
metricA, err := p.ParseLine(`1.25 200 192.168.1.1 5.432µs`)
|
|
require.NotNil(t, metricA)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t,
|
|
map[string]interface{}{
|
|
"clientip": "192.168.1.1",
|
|
"myfloat": "1.25",
|
|
"rt": "5.432µs",
|
|
},
|
|
metricA.Fields())
|
|
assert.Equal(t, map[string]string{}, metricA.Tags())
|
|
}
|
|
|
|
func TestCompileNoNamesAndParse(t *testing.T) {
|
|
p := &Parser{
|
|
Patterns: []string{"%{TEST_LOG_C}"},
|
|
CustomPatterns: `
|
|
DURATION %{NUMBER}[nuµm]?s
|
|
TEST_LOG_C %{NUMBER} %{NUMBER} %{IPORHOST} %{DURATION}
|
|
`,
|
|
}
|
|
assert.NoError(t, p.Compile())
|
|
|
|
metricA, err := p.ParseLine(`1.25 200 192.168.1.1 5.432µs`)
|
|
require.Nil(t, metricA)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestParseNoMatch(t *testing.T) {
|
|
p := &Parser{
|
|
Patterns: []string{"%{TEST_LOG_A}", "%{TEST_LOG_B}"},
|
|
CustomPatternFiles: []string{"./testdata/test-patterns"},
|
|
}
|
|
assert.NoError(t, p.Compile())
|
|
|
|
metricA, err := p.ParseLine(`[04/Jun/2016:12:41:45 +0100] notnumber 200 192.168.1.1 5.432µs 101`)
|
|
assert.NoError(t, err)
|
|
assert.Nil(t, metricA)
|
|
}
|
|
|
|
func TestCompileErrors(t *testing.T) {
|
|
// Compile fails because there are multiple timestamps:
|
|
p := &Parser{
|
|
Patterns: []string{"%{TEST_LOG_A}", "%{TEST_LOG_B}"},
|
|
CustomPatterns: `
|
|
TEST_LOG_A %{HTTPDATE:ts1:ts-httpd} %{HTTPDATE:ts2:ts-httpd} %{NUMBER:mynum:int}
|
|
`,
|
|
}
|
|
assert.Error(t, p.Compile())
|
|
|
|
// Compile fails because file doesn't exist:
|
|
p = &Parser{
|
|
Patterns: []string{"%{TEST_LOG_A}", "%{TEST_LOG_B}"},
|
|
CustomPatternFiles: []string{"/tmp/foo/bar/baz"},
|
|
}
|
|
assert.Error(t, p.Compile())
|
|
}
|
|
|
|
func TestParseErrors(t *testing.T) {
|
|
// Parse fails because the pattern doesn't exist
|
|
p := &Parser{
|
|
Patterns: []string{"%{TEST_LOG_B}"},
|
|
CustomPatterns: `
|
|
TEST_LOG_A %{HTTPDATE:ts:ts-httpd} %{WORD:myword:int} %{}
|
|
`,
|
|
}
|
|
assert.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)
|
|
|
|
// Parse fails because myword is not an int
|
|
p = &Parser{
|
|
Patterns: []string{"%{TEST_LOG_A}"},
|
|
CustomPatterns: `
|
|
TEST_LOG_A %{HTTPDATE:ts:ts-httpd} %{WORD:myword:int}
|
|
`,
|
|
}
|
|
assert.NoError(t, p.Compile())
|
|
_, err = p.ParseLine(`04/Jun/2016:12:41:45 +0100 notnumber`)
|
|
assert.Error(t, err)
|
|
|
|
// Parse fails because myword is not a float
|
|
p = &Parser{
|
|
Patterns: []string{"%{TEST_LOG_A}"},
|
|
CustomPatterns: `
|
|
TEST_LOG_A %{HTTPDATE:ts:ts-httpd} %{WORD:myword:float}
|
|
`,
|
|
}
|
|
assert.NoError(t, p.Compile())
|
|
_, err = p.ParseLine(`04/Jun/2016:12:41:45 +0100 notnumber`)
|
|
assert.Error(t, err)
|
|
|
|
// Parse fails because myword is not a duration
|
|
p = &Parser{
|
|
Patterns: []string{"%{TEST_LOG_A}"},
|
|
CustomPatterns: `
|
|
TEST_LOG_A %{HTTPDATE:ts:ts-httpd} %{WORD:myword:duration}
|
|
`,
|
|
}
|
|
assert.NoError(t, p.Compile())
|
|
_, err = p.ParseLine(`04/Jun/2016:12:41:45 +0100 notnumber`)
|
|
assert.Error(t, err)
|
|
|
|
// Parse fails because the time layout is wrong.
|
|
p = &Parser{
|
|
Patterns: []string{"%{TEST_LOG_A}"},
|
|
CustomPatterns: `
|
|
TEST_LOG_A %{HTTPDATE:ts:ts-unix} %{WORD:myword:duration}
|
|
`,
|
|
}
|
|
assert.NoError(t, p.Compile())
|
|
_, err = p.ParseLine(`04/Jun/2016:12:41:45 +0100 notnumber`)
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
func TestTsModder(t *testing.T) {
|
|
tsm := &tsModder{}
|
|
|
|
reftime := time.Date(2006, time.December, 1, 1, 1, 1, int(time.Millisecond), time.UTC)
|
|
modt := tsm.tsMod(reftime)
|
|
assert.Equal(t, reftime, modt)
|
|
modt = tsm.tsMod(reftime)
|
|
assert.Equal(t, reftime.Add(time.Microsecond*1), modt)
|
|
modt = tsm.tsMod(reftime)
|
|
assert.Equal(t, reftime.Add(time.Microsecond*2), modt)
|
|
modt = tsm.tsMod(reftime)
|
|
assert.Equal(t, reftime.Add(time.Microsecond*3), modt)
|
|
|
|
reftime = time.Date(2006, time.December, 1, 1, 1, 1, int(time.Microsecond), time.UTC)
|
|
modt = tsm.tsMod(reftime)
|
|
assert.Equal(t, reftime, modt)
|
|
modt = tsm.tsMod(reftime)
|
|
assert.Equal(t, reftime.Add(time.Nanosecond*1), modt)
|
|
modt = tsm.tsMod(reftime)
|
|
assert.Equal(t, reftime.Add(time.Nanosecond*2), modt)
|
|
modt = tsm.tsMod(reftime)
|
|
assert.Equal(t, reftime.Add(time.Nanosecond*3), modt)
|
|
|
|
reftime = time.Date(2006, time.December, 1, 1, 1, 1, int(time.Microsecond)*999, time.UTC)
|
|
modt = tsm.tsMod(reftime)
|
|
assert.Equal(t, reftime, modt)
|
|
modt = tsm.tsMod(reftime)
|
|
assert.Equal(t, reftime.Add(time.Nanosecond*1), modt)
|
|
modt = tsm.tsMod(reftime)
|
|
assert.Equal(t, reftime.Add(time.Nanosecond*2), modt)
|
|
modt = tsm.tsMod(reftime)
|
|
assert.Equal(t, reftime.Add(time.Nanosecond*3), modt)
|
|
|
|
reftime = time.Date(2006, time.December, 1, 1, 1, 1, 0, time.UTC)
|
|
modt = tsm.tsMod(reftime)
|
|
assert.Equal(t, reftime, modt)
|
|
modt = tsm.tsMod(reftime)
|
|
assert.Equal(t, reftime.Add(time.Millisecond*1), modt)
|
|
modt = tsm.tsMod(reftime)
|
|
assert.Equal(t, reftime.Add(time.Millisecond*2), modt)
|
|
modt = tsm.tsMod(reftime)
|
|
assert.Equal(t, reftime.Add(time.Millisecond*3), modt)
|
|
|
|
reftime = time.Time{}
|
|
modt = tsm.tsMod(reftime)
|
|
assert.Equal(t, reftime, modt)
|
|
}
|
|
|
|
func TestTsModder_Rollover(t *testing.T) {
|
|
tsm := &tsModder{}
|
|
|
|
reftime := time.Date(2006, time.December, 1, 1, 1, 1, int(time.Millisecond), time.UTC)
|
|
modt := tsm.tsMod(reftime)
|
|
for i := 1; i < 1000; i++ {
|
|
modt = tsm.tsMod(reftime)
|
|
}
|
|
assert.Equal(t, reftime.Add(time.Microsecond*999+time.Nanosecond), modt)
|
|
|
|
reftime = time.Date(2006, time.December, 1, 1, 1, 1, int(time.Microsecond), time.UTC)
|
|
modt = tsm.tsMod(reftime)
|
|
for i := 1; i < 1001; i++ {
|
|
modt = tsm.tsMod(reftime)
|
|
}
|
|
assert.Equal(t, reftime.Add(time.Nanosecond*1000), modt)
|
|
}
|