Skip to content

Commit 6b49a39

Browse files
glichtmcuadros
authored andcommitted
support for no priority as specified in rfc3164 section 4.3.3 (#57)
* support for no priority as specified in rfc3164 section 4.3.3 * set timestamp to now when no priority is specified
1 parent 277e703 commit 6b49a39

File tree

5 files changed

+97
-13
lines changed

5 files changed

+97
-13
lines changed

format/automatic.go

+16-10
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package format
33
import (
44
"bufio"
55
"bytes"
6-
"errors"
76
"strconv"
87

98
"gopkg.in/mcuadros/go-syslog.v2/internal/syslogparser/rfc3164"
@@ -31,33 +30,40 @@ const (
3130
detectedRFC6587 = iota
3231
)
3332

34-
func detect(data []byte) (detected int, err error) {
33+
/*
34+
* Will always fallback to rfc3164 (see section 4.3.3)
35+
*/
36+
func detect(data []byte) int {
3537
// all formats have a sapce somewhere
3638
if i := bytes.IndexByte(data, ' '); i > 0 {
3739
pLength := data[0:i]
3840
if _, err := strconv.Atoi(string(pLength)); err == nil {
39-
return detectedRFC6587, nil
41+
return detectedRFC6587
42+
}
43+
// are we starting with <
44+
if data[0] != '<' {
45+
return detectedRFC3164
4046
}
41-
4247
// is there a close angle bracket before the ' '? there should be
4348
angle := bytes.IndexByte(data, '>')
4449
if (angle < 0) || (angle >= i) {
45-
return detectedUnknown, errors.New("No close angle bracket before space")
50+
return detectedRFC3164
4651
}
4752

4853
// if a single digit immediately follows the angle bracket, then a space
4954
// it is RFC5424, as RFC3164 must begin with a letter (month name)
5055
if (angle+2 == i) && (data[angle+1] >= '0') && (data[angle+1] <= '9') {
51-
return detectedRFC5424, nil
56+
return detectedRFC5424
5257
} else {
53-
return detectedRFC3164, nil
58+
return detectedRFC3164
5459
}
5560
}
56-
return detectedUnknown, nil
61+
// fallback to rfc 3164 section 4.3.3
62+
return detectedRFC3164
5763
}
5864

5965
func (f *Automatic) GetParser(line []byte) LogParser {
60-
switch format, _ := detect(line); format {
66+
switch format := detect(line); format {
6167
case detectedRFC3164:
6268
return &parserWrapper{rfc3164.NewParser(line)}
6369
case detectedRFC5424:
@@ -82,7 +88,7 @@ func (f *Automatic) automaticScannerSplit(data []byte, atEOF bool) (advance int,
8288
return 0, nil, nil
8389
}
8490

85-
switch format, err := detect(data); format {
91+
switch format := detect(data); format {
8692
case detectedRFC6587:
8793
return rfc6587ScannerSplit(data, atEOF)
8894
case detectedRFC3164, detectedRFC5424:

internal/syslogparser/rfc3164/rfc3164.go

+12-2
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,22 @@ func (p *Parser) Location(location *time.Location) {
4444
}
4545

4646
func (p *Parser) Parse() error {
47+
tcursor := p.cursor
4748
pri, err := p.parsePriority()
4849
if err != nil {
49-
return err
50+
// RFC3164 sec 4.3.3
51+
p.priority = syslogparser.Priority{13, syslogparser.Facility{Value: 1}, syslogparser.Severity{Value: 5}}
52+
p.cursor = tcursor
53+
content, err := p.parseContent()
54+
p.header.timestamp = time.Now().Round(time.Second)
55+
if err != syslogparser.ErrEOL {
56+
return err
57+
}
58+
p.message = rfc3164message{content: content}
59+
return nil
5060
}
5161

52-
tcursor := p.cursor
62+
tcursor = p.cursor
5363
hdr, err := p.parseHeader()
5464
if err == syslogparser.ErrTimestampUnknownFormat {
5565
// RFC3164 sec 4.3.2.

internal/syslogparser/rfc3164/rfc3164_test.go

+49
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ func (s *Rfc3164TestSuite) TestParser_NoTimestamp(c *C) {
107107
now := time.Now()
108108

109109
obtained := p.Dump()
110+
111+
obtainedTime := obtained["timestamp"].(time.Time)
112+
s.assertTimeIsCloseToNow(c, obtainedTime)
113+
110114
obtained["timestamp"] = now // XXX: Need to mock out time to test this fully
111115
expected := syslogparser.LogParts{
112116
"timestamp": now,
@@ -121,6 +125,43 @@ func (s *Rfc3164TestSuite) TestParser_NoTimestamp(c *C) {
121125
c.Assert(obtained, DeepEquals, expected)
122126
}
123127

128+
// RFC 3164 section 4.3.3
129+
func (s *Rfc3164TestSuite) TestParser_NoPriority(c *C) {
130+
buff := []byte("Oct 11 22:14:15 Testing no priority")
131+
132+
p := NewParser(buff)
133+
expectedP := &Parser{
134+
buff: buff,
135+
cursor: 0,
136+
l: len(buff),
137+
location: time.UTC,
138+
}
139+
140+
c.Assert(p, DeepEquals, expectedP)
141+
142+
err := p.Parse()
143+
c.Assert(err, IsNil)
144+
145+
now := time.Now()
146+
147+
obtained := p.Dump()
148+
obtainedTime := obtained["timestamp"].(time.Time)
149+
s.assertTimeIsCloseToNow(c, obtainedTime)
150+
151+
obtained["timestamp"] = now // XXX: Need to mock out time to test this fully
152+
expected := syslogparser.LogParts{
153+
"timestamp": now,
154+
"hostname": "",
155+
"tag": "",
156+
"content": "Oct 11 22:14:15 Testing no priority",
157+
"priority": 13,
158+
"facility": 1,
159+
"severity": 5,
160+
}
161+
162+
c.Assert(obtained, DeepEquals, expected)
163+
}
164+
124165
func (s *Rfc3164TestSuite) TestParseHeader_Valid(c *C) {
125166
buff := []byte("Oct 11 22:14:15 mymachine ")
126167
now := time.Now()
@@ -375,3 +416,11 @@ func (s *Rfc3164TestSuite) assertRfc3164message(c *C, msg rfc3164message, b []by
375416
c.Assert(obtained, Equals, msg)
376417
c.Assert(p.cursor, Equals, expC)
377418
}
419+
420+
func (s *Rfc3164TestSuite) assertTimeIsCloseToNow(c *C, obtainedTime time.Time) {
421+
now := time.Now()
422+
timeStart := now.Add(-(time.Second * 5))
423+
timeEnd := now.Add(time.Second)
424+
c.Assert(obtainedTime.After(timeStart), Equals, true)
425+
c.Assert(obtainedTime.Before(timeEnd), Equals, true)
426+
}

server.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ func (s *Server) parser(line []byte, client string, tlsPeer string) {
258258

259259
logParts := parser.Dump()
260260
logParts["client"] = client
261-
if logParts["hostname"] == "" && s.format == RFC3164 {
261+
if logParts["hostname"] == "" && (s.format == RFC3164 || s.format == Automatic) {
262262
if i := strings.Index(client, ":"); i > 1 {
263263
logParts["hostname"] = client[:i]
264264
} else {

server_test.go

+19
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ type ServerSuite struct {
1919
var _ = Suite(&ServerSuite{})
2020
var exampleSyslog = "<31>Dec 26 05:08:46 hostname tag[296]: content"
2121
var exampleSyslogNoTSTagHost = "<14>INFO leaving (1) step postscripts"
22+
var exampleSyslogNoPriority = "Dec 26 05:08:46 hostname test with no priority - see rfc 3164 section 4.3.3"
2223
var exampleRFC5424Syslog = "<34>1 2003-10-11T22:14:15.003Z mymachine.example.com su - ID47 - 'su root' failed for lonvick on /dev/pts/8"
2324

2425
func (s *ServerSuite) TestTailFile(c *C) {
@@ -184,6 +185,24 @@ func (s *ServerSuite) TestUDP3164NoTag(c *C) {
184185
c.Check(handler.LastError, IsNil)
185186
}
186187

188+
func (s *ServerSuite) TestUDPAutomatic3164NoPriority(c *C) {
189+
handler := new(HandlerMock)
190+
server := NewServer()
191+
server.SetFormat(Automatic)
192+
server.SetHandler(handler)
193+
server.SetTimeout(10)
194+
server.goParseDatagrams()
195+
server.datagramChannel <- DatagramMessage{[]byte(exampleSyslogNoPriority), "127.0.0.1:45789"}
196+
close(server.datagramChannel)
197+
server.Wait()
198+
c.Check(handler.LastLogParts["hostname"], Equals, "127.0.0.1")
199+
c.Check(handler.LastLogParts["tag"], Equals, "")
200+
c.Check(handler.LastLogParts["priority"], Equals, 13)
201+
c.Check(handler.LastLogParts["content"], Equals, exampleSyslogNoPriority)
202+
c.Check(handler.LastMessageLength, Equals, int64(len(exampleSyslogNoPriority)))
203+
c.Check(handler.LastError, IsNil)
204+
}
205+
187206
func (s *ServerSuite) TestUDP6587(c *C) {
188207
handler := new(HandlerMock)
189208
server := NewServer()

0 commit comments

Comments
 (0)