Add special syslog timestamp parser that uses current year (#4190)
Previously it was impossible to parse syslog timestamps without the date being reported as year 0, due to the year not being specified
This commit is contained in:
parent
44e3b9bee3
commit
14d97e5416
|
@ -104,6 +104,7 @@ You must capture at least one field per line.
|
||||||
- ts-httpd ("02/Jan/2006:15:04:05 -0700")
|
- ts-httpd ("02/Jan/2006:15:04:05 -0700")
|
||||||
- ts-epoch (seconds since unix epoch, may contain decimal)
|
- ts-epoch (seconds since unix epoch, may contain decimal)
|
||||||
- ts-epochnano (nanoseconds since unix epoch)
|
- ts-epochnano (nanoseconds since unix epoch)
|
||||||
|
- ts-syslog ("Jan 02 15:04:05", parsed time is set to the current year)
|
||||||
- ts-"CUSTOM"
|
- ts-"CUSTOM"
|
||||||
|
|
||||||
CUSTOM time layouts must be within quotes and be the representation of the
|
CUSTOM time layouts must be within quotes and be the representation of the
|
||||||
|
|
|
@ -32,6 +32,7 @@ var timeLayouts = map[string]string{
|
||||||
// will get handled in the ParseLine function.
|
// will get handled in the ParseLine function.
|
||||||
"ts-epoch": "EPOCH",
|
"ts-epoch": "EPOCH",
|
||||||
"ts-epochnano": "EPOCH_NANO",
|
"ts-epochnano": "EPOCH_NANO",
|
||||||
|
"ts-syslog": "SYSLOG_TIMESTAMP",
|
||||||
"ts": "GENERIC_TIMESTAMP", // try parsing all known timestamp layouts.
|
"ts": "GENERIC_TIMESTAMP", // try parsing all known timestamp layouts.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +45,7 @@ const (
|
||||||
DROP = "drop"
|
DROP = "drop"
|
||||||
EPOCH = "EPOCH"
|
EPOCH = "EPOCH"
|
||||||
EPOCH_NANO = "EPOCH_NANO"
|
EPOCH_NANO = "EPOCH_NANO"
|
||||||
|
SYSLOG_TIMESTAMP = "SYSLOG_TIMESTAMP"
|
||||||
GENERIC_TIMESTAMP = "GENERIC_TIMESTAMP"
|
GENERIC_TIMESTAMP = "GENERIC_TIMESTAMP"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -112,6 +114,7 @@ type Parser struct {
|
||||||
// layouts.
|
// layouts.
|
||||||
foundTsLayouts []string
|
foundTsLayouts []string
|
||||||
|
|
||||||
|
timeFunc func() time.Time
|
||||||
g *grok.Grok
|
g *grok.Grok
|
||||||
tsModder *tsModder
|
tsModder *tsModder
|
||||||
}
|
}
|
||||||
|
@ -174,6 +177,10 @@ func (p *Parser) Compile() error {
|
||||||
p.loc, _ = time.LoadLocation("UTC")
|
p.loc, _ = time.LoadLocation("UTC")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if p.timeFunc == nil {
|
||||||
|
p.timeFunc = time.Now
|
||||||
|
}
|
||||||
|
|
||||||
return p.compileCustomPatterns()
|
return p.compileCustomPatterns()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,6 +292,16 @@ func (p *Parser) ParseLine(line string) (telegraf.Metric, error) {
|
||||||
} else {
|
} else {
|
||||||
timestamp = time.Unix(0, iv)
|
timestamp = time.Unix(0, iv)
|
||||||
}
|
}
|
||||||
|
case SYSLOG_TIMESTAMP:
|
||||||
|
ts, err := time.ParseInLocation("Jan 02 15:04:05", v, p.loc)
|
||||||
|
if err == nil {
|
||||||
|
if ts.Year() == 0 {
|
||||||
|
ts = ts.AddDate(timestamp.Year(), 0, 0)
|
||||||
|
}
|
||||||
|
timestamp = ts
|
||||||
|
} else {
|
||||||
|
log.Printf("E! Error parsing %s to time layout [%s]: %s", v, t, err)
|
||||||
|
}
|
||||||
case GENERIC_TIMESTAMP:
|
case GENERIC_TIMESTAMP:
|
||||||
var foundTs bool
|
var foundTs bool
|
||||||
// first try timestamp layouts that we've already found
|
// first try timestamp layouts that we've already found
|
||||||
|
|
|
@ -970,3 +970,15 @@ func TestNewlineInPatterns(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, m)
|
require.NotNil(t, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSyslogTimestampParser(t *testing.T) {
|
||||||
|
p := &Parser{
|
||||||
|
Patterns: []string{`%{SYSLOGTIMESTAMP:timestamp:ts-syslog} value=%{NUMBER:value:int}`},
|
||||||
|
timeFunc: func() time.Time { return time.Date(2018, time.April, 1, 0, 0, 0, 0, nil) },
|
||||||
|
}
|
||||||
|
require.NoError(t, p.Compile())
|
||||||
|
m, err := p.ParseLine("Sep 25 09:01:55 value=42")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, m)
|
||||||
|
require.Equal(t, 2018, m.Time().Year())
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue