Skip to content
This repository has been archived by the owner on May 21, 2024. It is now read-only.

Allow skipping Pri header. #53

Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 32 additions & 16 deletions rfc3164/machine.go.rl
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,14 @@ action err_prival {
}

action err_pri {
m.err = fmt.Errorf(errPri, m.p)
fhold;
fgoto fail;
if(!m.allowSkipPri) {
m.err = fmt.Errorf(errPri, m.p)
fhold;
fgoto fail;
} else {
fhold;
fgoto STATE_NO_PRI;
}
}

action err_timestamp {
Expand Down Expand Up @@ -158,23 +163,30 @@ msg = (tag content? ':' sp)? mex;

fail := (any - [\n\r])* @err{ fgoto main; };

main := pri (timestamp | (rfc3339 when { m.rfc3339 })) sp hostname sp msg;
sysmessage = (timestamp | (rfc3339 when { m.rfc3339 })) sp hostname sp msg;

myfsm := (
STATE_NO_PRI: sysmessage
);

main := pri sysmessage;

}%%

%% write data noerror noprefix;

type machine struct {
data []byte
cs int
p, pe, eof int
pb int
err error
bestEffort bool
yyyy int
rfc3339 bool
loc *time.Location
timezone *time.Location
data []byte
cs int
p, pe, eof int
pb int
err error
bestEffort bool
yyyy int
rfc3339 bool
allowSkipPri bool
loc *time.Location
timezone *time.Location
}

// NewMachine creates a new FSM able to parse RFC3164 syslog messages.
Expand All @@ -194,6 +206,11 @@ func NewMachine(options ...syslog.MachineOption) syslog.Machine {
return m
}

// WithNoPri sets the skip PRI flag to allow messages without PRI header.
func (m *machine) WithAllowSkipPri() {
m.allowSkipPri = true
}

// WithBestEffort enables best effort mode.
func (m *machine) WithBestEffort() {
m.bestEffort = true
Expand Down Expand Up @@ -259,5 +276,4 @@ func (m *machine) Parse(input []byte) (syslog.Message, error) {
}

return output.export(), nil
}

}
82 changes: 62 additions & 20 deletions rfc3164/machine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,19 @@ import (
// todo > add support for testing `best effort` mode

type testCase struct {
input []byte
valid bool
value syslog.Message
errorString string
partialValue syslog.Message
input []byte
valid bool
shouldSkipPri bool
value syslog.Message
errorString string
partialValue syslog.Message
}

var testCases = []testCase{
{
[]byte(`<34>Jan 12 06:30:00 xxx apache: 1.2.3.4 - - [12/Jan/2011:06:29:59 +0100] "GET /foo/bar.html HTTP/1.1" 301 96 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12 ( .NET CLR 3.5.30729)" PID 18904 Time Taken 0`),
true,
false,
&SyslogMessage{
Base: syslog.Base{
Priority: syslogtesting.Uint8Address(34),
Expand All @@ -40,6 +42,7 @@ var testCases = []testCase{
{
[]byte(`<34>Aug 7 06:30:00 xxx aaa: message from 1.2.3.4`),
true,
false,
&SyslogMessage{
Base: syslog.Base{
Priority: syslogtesting.Uint8Address(34),
Expand All @@ -55,8 +58,9 @@ var testCases = []testCase{
nil,
},
{
input: []byte(`<85>Jan 24 15:50:41 ip-172-31-30-110 sudo[6040]: ec2-user : TTY=pts/0 ; PWD=/var/log ; USER=root ; COMMAND=/bin/tail secure`),
valid: true,
input: []byte(`<85>Jan 24 15:50:41 ip-172-31-30-110 sudo[6040]: ec2-user : TTY=pts/0 ; PWD=/var/log ; USER=root ; COMMAND=/bin/tail secure`),
valid: true,
shouldSkipPri: false,
value: &SyslogMessage{
Base: syslog.Base{
Priority: syslogtesting.Uint8Address(85),
Expand All @@ -71,8 +75,9 @@ var testCases = []testCase{
},
},
{
input: []byte(`<166>Jul 6 20:33:28 ABC-1-234567 Some message here`),
valid: true,
input: []byte(`<166>Jul 6 20:33:28 ABC-1-234567 Some message here`),
valid: true,
shouldSkipPri: false,
value: &SyslogMessage{
Base: syslog.Base{
Priority: syslogtesting.Uint8Address(166),
Expand All @@ -85,8 +90,9 @@ var testCases = []testCase{
},
},
{
input: []byte(`<34>Oct 11 22:14:15 mymachine su: 'su root' failed for lonvick on /dev/pts/8`),
valid: true,
input: []byte(`<34>Oct 11 22:14:15 mymachine su: 'su root' failed for lonvick on /dev/pts/8`),
valid: true,
shouldSkipPri: false,
value: &SyslogMessage{
Base: syslog.Base{
Priority: syslogtesting.Uint8Address(34),
Expand All @@ -100,8 +106,9 @@ var testCases = []testCase{
},
},
{
input: []byte(`<13>Feb 5 17:32:18 10.0.0.99 Use the BFG!`),
valid: true,
input: []byte(`<13>Feb 5 17:32:18 10.0.0.99 Use the BFG!`),
valid: true,
shouldSkipPri: false,
value: &SyslogMessage{
Base: syslog.Base{
Priority: syslogtesting.Uint8Address(13),
Expand All @@ -114,8 +121,9 @@ var testCases = []testCase{
},
},
{
input: []byte(`<165>Aug 24 05:34:00 mymachine myproc[10]: %% It's time to make the do-nuts. %% Ingredients: Mix=OK, Jelly=OK # Devices: Mixer=OK, Jelly_Injector=OK, Frier=OK # Transport: Conveyer1=OK, Conveyer2=OK # %%`),
valid: true,
input: []byte(`<165>Aug 24 05:34:00 mymachine myproc[10]: %% It's time to make the do-nuts. %% Ingredients: Mix=OK, Jelly=OK # Devices: Mixer=OK, Jelly_Injector=OK, Frier=OK # Transport: Conveyer1=OK, Conveyer2=OK # %%`),
valid: true,
shouldSkipPri: false,
value: &SyslogMessage{
Base: syslog.Base{
Priority: syslogtesting.Uint8Address(165),
Expand All @@ -130,8 +138,9 @@ var testCases = []testCase{
},
},
{
input: []byte(`<0>Oct 22 10:52:01 10.1.2.3 sched[0]: That's All Folks!`),
valid: true,
input: []byte(`<0>Oct 22 10:52:01 10.1.2.3 sched[0]: That's All Folks!`),
valid: true,
shouldSkipPri: false,
value: &SyslogMessage{
Base: syslog.Base{
Priority: syslogtesting.Uint8Address(0),
Expand All @@ -145,6 +154,30 @@ var testCases = []testCase{
},
},
},
{
input: []byte(`Oct 22 10:52:01 10.1.2.3 sched[0]: That's All Folks!`),
valid: true,
shouldSkipPri: true,
value: &SyslogMessage{
Base: syslog.Base{
Priority: syslogtesting.Uint8Address(0),
Facility: syslogtesting.Uint8Address(0),
Severity: syslogtesting.Uint8Address(0),
Timestamp: syslogtesting.TimeParse(time.Stamp, "Oct 22 10:52:01"),
Hostname: syslogtesting.StringAddress("10.1.2.3"),
Appname: syslogtesting.StringAddress("sched"),
ProcID: syslogtesting.StringAddress("0"),
Message: syslogtesting.StringAddress(`That's All Folks!`),
},
},
},
{
input: []byte(`Oct 22 10:52:01 10.1.2.3 sched[0]: That's All Folks!`),
valid: false,
shouldSkipPri: false,
value: nil,
errorString: "expecting a priority value within angle brackets [col 0]",
},
// todo > other test cases pleaaaase
}

Expand All @@ -153,9 +186,16 @@ func TestMachineParse(t *testing.T) {
tc := tc
t.Run(syslogtesting.RightPad(string(tc.input), 50), func(t *testing.T) {
t.Parallel()
var merr, perr error
var message, partial syslog.Message

message, merr := NewMachine().Parse(tc.input)
partial, perr := NewMachine(WithBestEffort()).Parse(tc.input)
if tc.shouldSkipPri {
message, merr = NewMachine(WithAllowSkipPri()).Parse(tc.input)
partial, perr = NewMachine(WithBestEffort(), WithAllowSkipPri()).Parse(tc.input)
} else {
message, merr = NewMachine().Parse(tc.input)
partial, perr = NewMachine(WithBestEffort()).Parse(tc.input)
}

if !tc.valid {
assert.Nil(t, message)
Expand All @@ -172,7 +212,9 @@ func TestMachineParse(t *testing.T) {
assert.Equal(t, merr, perr)
}

assert.Equal(t, tc.value, message)
if tc.errorString != "" {
assert.Equal(t, tc.value, message)
}
})
}
}
8 changes: 8 additions & 0 deletions rfc3164/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ import (
syslog "github.com/influxdata/go-syslog/v3"
)

// WithNoPri sets the skip PRI flag to allow messages without PRI header.
func WithAllowSkipPri() syslog.MachineOption {
return func(m syslog.Machine) syslog.Machine {
m.(*machine).WithAllowSkipPri()
return m
}
}

// WithBestEffort enables the best effort mode.
func WithBestEffort() syslog.MachineOption {
return func(m syslog.Machine) syslog.Machine {
Expand Down
28 changes: 23 additions & 5 deletions rfc5424/machine.go.rl
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,14 @@ action err_prival {
}

action err_pri {
m.err = fmt.Errorf(ErrPri + ColumnPositionTemplate, m.p)
fhold;
fgoto fail;
if(!m.allowSkipPri) {
m.err = fmt.Errorf(ErrPri + ColumnPositionTemplate, m.p)
fhold;
fgoto fail;
} else {
fhold;
fgoto STATE_NO_PRI;
}
}

action err_version {
Expand Down Expand Up @@ -277,7 +282,6 @@ procid = procidrange >mark %set_procid $err(err_procid);

msgid = msgidrange >mark %set_msgid $err(err_msgid);

header = (pri version sp timestamp sp hostname sp appname sp procid sp msgid) <>err(err_parse);

# \", \], \\
escapes = (bs >add_slash toescape) $err(err_escape);
Expand Down Expand Up @@ -309,7 +313,15 @@ msg = any? @select_msg_mode;

fail := (any - [\n\r])* @err{ fgoto main; };

main := header sp structureddata (sp msg)? $err(err_parse);
headerwithnopri = ((version sp timestamp sp hostname sp appname sp procid sp msgid) <>err(err_parse)) sp structureddata (sp msg)? $err(err_parse);

header = pri headerwithnopri;

myfsm := (
STATE_NO_PRI: headerwithnopri
);

main := header;

}%%

Expand All @@ -327,6 +339,7 @@ type machine struct {
backslashat []int
bestEffort bool
compliantMsg bool
allowSkipPri bool
}

// NewMachine creates a new FSM able to parse RFC5424 syslog messages.
Expand All @@ -346,6 +359,11 @@ func NewMachine(options ...syslog.MachineOption) syslog.Machine {
return m
}

// WithNoPri sets the skip PRI flag to allow messages without PRI header.
func (m *machine) WithAllowSkipPri() {
m.allowSkipPri = true
}

// WithBestEffort enables best effort mode.
func (m *machine) WithBestEffort() {
m.bestEffort = true
Expand Down
Loading