Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Syslog rfc3164 location (timestamp) parameter #247

Merged
merged 3 commits into from
Feb 3, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased

### Added

- uri_parser operator for parsing [absolute uri, relative uri, and uri query strings](https://tools.ietf.org/html/rfc3986)
- container image: added package [tzdata](https://github.com/observIQ/stanza/pull/245)
- container image: added package [tzdata](https://github.com/observIQ/stanza/pull/245)

### Changed
- Added optional `location` parameter to Syslog operator [pr247](https://github.com/observIQ/stanza/pull/247)

## [0.13.12] - 2020-01-26

Expand Down
1 change: 1 addition & 0 deletions docs/operators/syslog_parser.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ The `syslog_parser` operator parses the string-type field selected by `parse_fro
| `preserve_to` | | Preserves the unparsed value at the specified [field](/docs/types/field.md) |
| `on_error` | `send` | The behavior of the operator if it encounters an error. See [on_error](/docs/types/on_error.md) |
| `protocol` | required | The protocol to parse the syslog messages as. Options are `rfc3164` and `rfc5424` |
| `location` | `UTC` | The geographic location (timezone) to use when parsing the timestamp (Syslog RFC 3164 only). The available locations depend on the local IANA Time Zone database. [This page](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) contains many examples, such as `America/New_York`. |
| `timestamp` | `nil` | An optional [timestamp](/docs/types/timestamp.md) block which will parse a timestamp field before passing the entry to the output operator |
| `severity` | `nil` | An optional [severity](/docs/types/severity.md) block which will parse a severity field before passing the entry to the output operator |
| `if` | | An [expression](/docs/types/expression.md) that, when set, will be evaluated to determine whether this operator should be used for the given entry. This allows you to do easy conditional parsing without branching logic with routers. |
Expand Down
18 changes: 15 additions & 3 deletions operator/builtin/parser/syslog/syslog.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type SyslogParserConfig struct {
helper.ParserConfig `yaml:",inline"`

Protocol string `json:"protocol,omitempty" yaml:"protocol,omitempty"`
Location string `json:"location,omitempty" yaml:"location,omitempty"`
}

// Build will build a JSON parser operator.
Expand All @@ -50,18 +51,28 @@ func (c SyslogParserConfig) Build(context operator.BuildContext) ([]operator.Ope
return nil, fmt.Errorf("missing field 'protocol'")
}

if c.Location == "" {
c.Location = "UTC"
}

location, err := time.LoadLocation(c.Location)
if err != nil {
return nil, err
}

syslogParser := &SyslogParser{
ParserOperator: parserOperator,
protocol: c.Protocol,
location: location,
}

return []operator.Operator{syslogParser}, nil
}

func buildMachine(protocol string) (sl.Machine, error) {
func buildMachine(protocol string, location *time.Location) (sl.Machine, error) {
switch protocol {
case "rfc3164":
return rfc3164.NewMachine(), nil
return rfc3164.NewMachine(rfc3164.WithLocaleTimezone(location)), nil
case "rfc5424":
return rfc5424.NewMachine(), nil
default:
Expand All @@ -73,6 +84,7 @@ func buildMachine(protocol string) (sl.Machine, error) {
type SyslogParser struct {
helper.ParserOperator
protocol string
location *time.Location
}

// Process will parse an entry field as syslog.
Expand All @@ -90,7 +102,7 @@ func (s *SyslogParser) parse(value interface{}) (interface{}, error) {
return nil, err
}

machine, err := buildMachine(s.protocol)
machine, err := buildMachine(s.protocol, s.location)
if err != nil {
return nil, err
}
Expand Down
63 changes: 62 additions & 1 deletion operator/builtin/parser/syslog/syslog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,33 @@ import (
"github.com/stretchr/testify/require"
)

func testLocations() (map[string]*time.Location, error) {
locations := map[string]string{
"utc": "UTC",
"detroit": "America/Detroit",
"athens": "Europe/Athens",
}

l := make(map[string]*time.Location)
for k, v := range locations {
var err error
if l[k], err = time.LoadLocation(v); err != nil {
return nil, err
}
}
return l, nil
}

func TestSyslogParser(t *testing.T) {
basicConfig := func() *SyslogParserConfig {
cfg := NewSyslogParserConfig("test_operator_id")
cfg.OutputIDs = []string{"fake"}
return cfg
}

location, err := testLocations()
require.NoError(t, err)

cases := []struct {
name string
config *SyslogParserConfig
Expand All @@ -32,10 +52,51 @@ func TestSyslogParser(t *testing.T) {
func() *SyslogParserConfig {
cfg := basicConfig()
cfg.Protocol = "rfc3164"
cfg.Location = location["utc"].String()
return cfg
}(),
"<34>Jan 12 06:30:00 1.2.3.4 apache_server: test message",
time.Date(time.Now().Year(), 1, 12, 6, 30, 0, 0, time.UTC),
time.Date(time.Now().Year(), 1, 12, 6, 30, 0, 0, location["utc"]),
map[string]interface{}{
"appname": "apache_server",
"facility": 4,
"hostname": "1.2.3.4",
"message": "test message",
"priority": 34,
},
entry.Critical,
"crit",
},
{
"RFC3164Detroit",
func() *SyslogParserConfig {
cfg := basicConfig()
cfg.Protocol = "rfc3164"
cfg.Location = location["detroit"].String()
return cfg
}(),
"<34>Jan 12 06:30:00 1.2.3.4 apache_server: test message",
time.Date(time.Now().Year(), 1, 12, 6, 30, 0, 0, location["detroit"]),
map[string]interface{}{
"appname": "apache_server",
"facility": 4,
"hostname": "1.2.3.4",
"message": "test message",
"priority": 34,
},
entry.Critical,
"crit",
},
{
"RFC3164Athens",
func() *SyslogParserConfig {
cfg := basicConfig()
cfg.Protocol = "rfc3164"
cfg.Location = location["athens"].String()
return cfg
}(),
"<34>Jan 12 06:30:00 1.2.3.4 apache_server: test message",
time.Date(time.Now().Year(), 1, 12, 6, 30, 0, 0, location["athens"]),
map[string]interface{}{
"appname": "apache_server",
"facility": 4,
Expand Down