Skip to content

Commit cc9f411

Browse files
committed
lib/logstorage: follow-up for the commit d378ec6
- Make sure that the JSONParser lifetime is bigger than the lifetime of the @Cee fields parsed with it. - Add support for parsing @Cee message inside RFC5424 protocol. - Document the added functionality in the Syslog data ingestion docs - https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/#cee - Mention the added functionality in the https://docs.victoriametrics.com/victorialogs/changelog/ Updates #842
1 parent d378ec6 commit cc9f411

File tree

5 files changed

+58
-25
lines changed

5 files changed

+58
-25
lines changed

docs/victorialogs/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ according to the follosing docs:
2121

2222
## tip
2323

24+
* FEATURE: [syslog data ingestion](https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/): add support for automatic parsing of [`@cee` messages](http://cee.mitre.org/language/1.0-beta1/clt.html#syslog). Thanks to @exherb for the pull request [#842](https://github.com/VictoriaMetrics/VictoriaLogs/pull/842).
25+
2426
* BUGFIX: [delete API](https://docs.victoriametrics.com/victorialogs/#how-to-delete-logs): prevent from possible fatal error (panic) at `block_stream_merger.go:237` during the deletion of the logs. See [#825](https://github.com/VictoriaMetrics/VictoriaLogs/issues/825).
2527

2628
## [v1.38.0](https://github.com/VictoriaMetrics/VictoriaLogs/releases/tag/v1.38.0)

docs/victorialogs/data-ingestion/syslog.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,11 @@ VictoriaLogs automatically parses [CEF Syslog messages for SIEM](https://www.mic
197197

198198
An optional `extension` fields are parsed into `cef.extension.<key>=<value>` fields.
199199

200+
## CEE
201+
202+
VictoriaLogs automatically parses [`@cee` messages](http://cee.mitre.org/language/1.0-beta1/clt.html#syslog) into distinct log fields.
203+
See [these docs](https://www.rsyslog.com/json-elasticsearch/) for more details.
204+
200205
## Dropping fields
201206

202207
VictoriaLogs supports `-syslog.ignoreFields.tcp`, `-syslog.ignoreFields.udp` and `-syslog.ignoreFields.unix` command-line flags for skipping

lib/logstorage/json_parser.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ import (
1212
//
1313
// See https://docs.victoriametrics.com/victorialogs/keyconcepts/#data-model
1414
//
15-
// Use GetParser() for obtaining the parser.
15+
// Use GetJSONParser() for obtaining the parser.
1616
type JSONParser struct {
1717
// Fields contains the parsed JSON line after Parse() call
1818
//
1919
// The Fields are valid until the next call to ParseLogMessage()
20-
// or until the parser is returned to the pool with PutParser() call.
20+
// or until the parser is returned to the pool with PutJSONParser() call.
2121
Fields []Field
2222

2323
// p is used for fast JSON parsing

lib/logstorage/syslog_parser.go

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77

88
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
99
"github.com/VictoriaMetrics/VictoriaMetrics/lib/fasttime"
10-
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
1110
)
1211

1312
// GetSyslogParser returns syslog parser from the pool.
@@ -61,6 +60,11 @@ type SyslogParser struct {
6160
// See https://datatracker.ietf.org/doc/html/rfc5424#section-6.3
6261
sdParser logfmtParser
6362

63+
// jsonParser is used for parsing CEE messages.
64+
//
65+
// See https://cee.mitre.org/language/1.0-beta1/clt.html#syslog
66+
jsonParser *JSONParser
67+
6468
// currentYear is used as the current year for rfc3164 messages.
6569
currentYear int
6670

@@ -72,6 +76,11 @@ type SyslogParser struct {
7276
}
7377

7478
func (p *SyslogParser) reset() {
79+
if p.jsonParser != nil {
80+
PutJSONParser(p.jsonParser)
81+
p.jsonParser = nil
82+
}
83+
7584
p.currentYear = 0
7685
p.timezone = nil
7786
p.resetFields()
@@ -83,30 +92,44 @@ func (p *SyslogParser) resetFields() {
8392

8493
p.buf = p.buf[:0]
8594
p.sdParser.reset()
95+
96+
if p.jsonParser != nil {
97+
p.jsonParser.reset()
98+
}
8699
}
87100

88101
func (p *SyslogParser) AddMessageField(s string) {
89-
if strings.HasPrefix(s, "CEF:") {
90-
fields := p.Fields
91-
if p.parseCEFMessage(strings.TrimPrefix(s, "CEF:")) {
92-
return
93-
}
102+
fields := p.Fields
103+
if !p.parseSpecialMessage(s) {
94104
p.Fields = fields
105+
p.AddField("message", s)
95106
}
107+
}
96108

97-
if strings.HasPrefix(s, "@cee:") {
98-
jsonP := GetJSONParser()
99-
defer PutJSONParser(jsonP)
100-
jsonStr := strings.TrimPrefix(s, "@cee:")
101-
if err := jsonP.ParseLogMessage(bytesutil.ToUnsafeBytes(jsonStr)); err == nil {
102-
p.Fields = append(p.Fields, jsonP.Fields...)
103-
return
104-
} else {
105-
logger.Warnf("parse @cee json fail, %s", jsonStr)
106-
}
109+
func (p *SyslogParser) parseSpecialMessage(s string) bool {
110+
switch {
111+
case strings.HasPrefix(s, "CEF:"):
112+
cefStr := strings.TrimPrefix(s, "CEF:")
113+
return p.parseCEFMessage(cefStr)
114+
case strings.HasPrefix(s, "@cee:"):
115+
ceeStr := strings.TrimPrefix(s, "@cee:")
116+
return p.parseCEEMessage(ceeStr)
117+
default:
118+
return false
107119
}
120+
}
108121

109-
p.AddField("message", s)
122+
// parseCEEMessage parses CEE message. See https://cee.mitre.org/language/1.0-beta1/clt.html#syslog
123+
func (p *SyslogParser) parseCEEMessage(s string) bool {
124+
if p.jsonParser == nil {
125+
p.jsonParser = GetJSONParser()
126+
}
127+
err := p.jsonParser.ParseLogMessage(bytesutil.ToUnsafeBytes(s))
128+
if err != nil {
129+
return false
130+
}
131+
p.Fields = append(p.Fields, p.jsonParser.Fields...)
132+
return true
110133
}
111134

112135
// AddField adds name=value log field to p.Fields.
@@ -328,7 +351,10 @@ func (p *SyslogParser) parseRFC5424(s string) {
328351

329352
func (p *SyslogParser) parseRFC5424SD(s string) (string, bool) {
330353
if strings.HasPrefix(s, "- ") {
331-
return s[2:], true
354+
return s[len("- "):], true
355+
}
356+
if strings.HasPrefix(s, "@cee:") {
357+
return s, true
332358
}
333359

334360
for {

lib/logstorage/syslog_parser_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,9 @@ func TestSyslogParser(t *testing.T) {
123123
f(`Sep 29 08:26:10 host`, time.UTC, `format=rfc3164 timestamp=2024-09-29T08:26:10Z hostname=host`)
124124
f(`Sep 29 08:26:10`, time.UTC, `format=rfc3164 timestamp=2024-09-29T08:26:10Z`)
125125

126-
// @cee
127-
f(`Jun 3 12:08:33 abcd systemd[1]: @cee: {"k":"v","message":"test"}`, time.UTC,
128-
`format=rfc3164 timestamp=2024-06-03T12:08:33Z hostname=abcd app_name=systemd proc_id=1 k=v message=test`)
129-
f(`Jun 3 12:08:33 abcd systemd[1]: @cee: {"k":"v","message":"two words"}`, time.UTC,
130-
`format=rfc3164 timestamp=2024-06-03T12:08:33Z hostname=abcd app_name=systemd proc_id=1 k=v message="two words"`)
126+
// @cee - https://cee.mitre.org/language/1.0-beta1/clt.html#syslog
127+
f(`Jun 3 12:08:33 abcd systemd[1]: @cee: {"k":"v","message":"test"}`, time.UTC, `format=rfc3164 timestamp=2024-06-03T12:08:33Z hostname=abcd app_name=systemd proc_id=1 k=v message=test`)
128+
f(`Jun 3 12:08:33 abcd systemd[1]: @cee: {"k":"v","message":"two words"}`, time.UTC, `format=rfc3164 timestamp=2024-06-03T12:08:33Z hostname=abcd app_name=systemd proc_id=1 k=v message="two words"`)
129+
f(`<0>Dec 20 12:42:20 syslog-relay process[35]: @cee: {"crit":123,"id":"abc","appname":"application","pname":"auth","pid":123,"host":"system.example.com","pri":10,"time":"2011-12-20T12:38:05.123456-05:00","action":"login","domain":"app","object":"account","service":"web","status":"success"}`, time.UTC, `priority=0 facility_keyword=kern level=emerg facility=0 severity=0 format=rfc3164 timestamp=2024-12-20T12:42:20Z hostname=syslog-relay app_name=process proc_id=35 crit=123 id=abc appname=application pname=auth pid=123 host=system.example.com pri=10 time=2011-12-20T12:38:05.123456-05:00 action=login domain=app object=account service=web status=success`)
130+
f(`<165>1 2011-12-20T12:38:06Z 10.10.0.1 process - example-event-1 @cee:{"pname":"auth","host":"system.example.com","time":"2011-12-20T12:38:05.123456-05:00"}`, time.UTC, `priority=165 facility_keyword=local4 level=notice facility=20 severity=5 format=rfc5424 timestamp=2011-12-20T12:38:06Z hostname=10.10.0.1 app_name=process proc_id=- msg_id=example-event-1 pname=auth host=system.example.com time=2011-12-20T12:38:05.123456-05:00`)
131131
}

0 commit comments

Comments
 (0)