Skip to content

Commit

Permalink
[exporter/syslog] Add support for octet counting in the syslog export…
Browse files Browse the repository at this point in the history
…er (open-telemetry#31014)

**Description:** <Describe what has changed.>

This introduces a new configuration `enable_octet_counting` which
matches the same configuration on the syslog receiver side, and if
enabled will append the length of the message to the start of the
message.

**Link to tracking Issue:**  open-telemetry#31013

**Testing:**

Added tests alongside the existing syslog exporter tests

**Documentation:**

Updated the README with the new config option

Signed-off-by: sinkingpoint <[email protected]>
  • Loading branch information
sinkingpoint authored Feb 13, 2024
1 parent a95f8d4 commit e140374
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 9 deletions.
27 changes: 27 additions & 0 deletions .chloggen/sinkingpoint_octet_counting.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: syslogexporter

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Adding support for sending rfc6587 octet counts in syslog messages

# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: [31013]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:

# If your change doesn't affect end users or the exported elements of any package,
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: []
1 change: 1 addition & 0 deletions exporter/syslogexporter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ This means that syslog messages received via the Syslog receiver and exported vi
- `protocol` - (default = `rfc5424`) rfc5424/rfc3164
- `rfc5424` - Expects the syslog messages to be rfc5424 compliant
- `rfc3164` - Expects the syslog messages to be rfc3164 compliant
- `enable_octet_counting` (default = `false`) - Whether or not to enable rfc6587 octet counting
- `tls` - configuration for TLS/mTLS
- `insecure` (default = `false`) whether to enable client transport security, by default, TLS is enabled.
- `cert_file` - Path to the TLS cert to use for TLS required connections. Should only be used if `insecure` is set to `false`.
Expand Down
8 changes: 8 additions & 0 deletions exporter/syslogexporter/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ var (
errInvalidEndpoint = errors.New("invalid endpoint: endpoint is required but it is not configured")
errUnsupportedNetwork = errors.New("unsupported network: network is required, only tcp/udp supported")
errUnsupportedProtocol = errors.New("unsupported protocol: Only rfc5424 and rfc3164 supported")
errOctetCounting = errors.New("octet counting is only supported for rfc5424 protocol")
)

// Config defines configuration for Syslog exporter.
Expand All @@ -33,6 +34,9 @@ type Config struct {
// options: rfc5424, rfc3164
Protocol string `mapstructure:"protocol"`

// Wether or not to enable RFC 6587 Octet Counting.
EnableOctetCounting bool `mapstructure:"enable_octet_counting"`

// TLSSetting struct exposes TLS client configuration.
TLSSetting configtls.TLSClientSetting `mapstructure:"tls"`

Expand Down Expand Up @@ -63,6 +67,10 @@ func (cfg *Config) Validate() error {
invalidFields = append(invalidFields, errUnsupportedProtocol)
}

if cfg.EnableOctetCounting && cfg.Protocol != protocolRFC5424Str {
invalidFields = append(invalidFields, errOctetCounting)
}

if len(invalidFields) > 0 {
return multierr.Combine(invalidFields...)
}
Expand Down
2 changes: 1 addition & 1 deletion exporter/syslogexporter/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func initExporter(cfg *Config, createSettings exporter.CreateSettings) (*sysloge
config: cfg,
logger: createSettings.Logger,
tlsConfig: tlsConfig,
formatter: createFormatter(cfg.Protocol),
formatter: createFormatter(cfg.Protocol, cfg.EnableOctetCounting),
}

s.logger.Info("Syslog Exporter configured",
Expand Down
4 changes: 2 additions & 2 deletions exporter/syslogexporter/formatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import (
"go.opentelemetry.io/collector/pdata/plog"
)

func createFormatter(protocol string) formatter {
func createFormatter(protocol string, octetCounting bool) formatter {
if protocol == protocolRFC5424Str {
return newRFC5424Formatter()
return newRFC5424Formatter(octetCounting)
}
return newRFC3164Formatter()
}
Expand Down
12 changes: 10 additions & 2 deletions exporter/syslogexporter/rfc5424_formatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@ import (
)

type rfc5424Formatter struct {
octetCounting bool
}

func newRFC5424Formatter() *rfc5424Formatter {
return &rfc5424Formatter{}
func newRFC5424Formatter(octetCounting bool) *rfc5424Formatter {
return &rfc5424Formatter{
octetCounting: octetCounting,
}
}

func (f *rfc5424Formatter) format(logRecord plog.LogRecord) string {
Expand All @@ -30,6 +33,11 @@ func (f *rfc5424Formatter) format(logRecord plog.LogRecord) string {
structuredData := f.formatStructuredData(logRecord)
messageString := f.formatMessage(logRecord)
formatted := fmt.Sprintf("<%s>%s %s %s %s %s %s %s%s\n", priorityString, versionString, timestampString, hostnameString, appnameString, pidString, messageIDString, structuredData, messageString)

if f.octetCounting {
formatted = fmt.Sprintf("%d %s", len(formatted), formatted)
}

return formatted
}

Expand Down
12 changes: 8 additions & 4 deletions exporter/syslogexporter/rfc5424_formatter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ func TestRFC5424Formatter(t *testing.T) {
require.NoError(t, err)
logRecord.SetTimestamp(pcommon.NewTimestampFromTime(timestamp))

actual := newRFC5424Formatter().format(logRecord)
actual := newRFC5424Formatter(false).format(logRecord)
assert.Equal(t, expected, actual)
octetCounting := newRFC5424Formatter(true).format(logRecord)
assert.Equal(t, fmt.Sprintf("%d %s", len(expected), expected), octetCounting)

expected = "<165>1 2003-10-11T22:14:15.003Z mymachine.example.com evntslog 111 ID47 - BOMAn application event log entry...\n"
logRecord = plog.NewLogRecord()
Expand All @@ -45,8 +47,10 @@ func TestRFC5424Formatter(t *testing.T) {
require.NoError(t, err)
logRecord.SetTimestamp(pcommon.NewTimestampFromTime(timestamp))

actual = newRFC5424Formatter().format(logRecord)
actual = newRFC5424Formatter(false).format(logRecord)
assert.Equal(t, expected, actual)
octetCounting = newRFC5424Formatter(true).format(logRecord)
assert.Equal(t, fmt.Sprintf("%d %s", len(expected), expected), octetCounting)

// Test structured data
expectedRegex := "\\<165\\>1 2003-08-24T12:14:15.000003Z 192\\.0\\.2\\.1 myproc 8710 - " +
Expand All @@ -72,7 +76,7 @@ func TestRFC5424Formatter(t *testing.T) {
require.NoError(t, err)
logRecord.SetTimestamp(pcommon.NewTimestampFromTime(timestamp))

actual = newRFC5424Formatter().format(logRecord)
actual = newRFC5424Formatter(false).format(logRecord)
assert.NoError(t, err)
matched, err := regexp.MatchString(expectedRegex, actual)
assert.NoError(t, err)
Expand All @@ -89,6 +93,6 @@ func TestRFC5424Formatter(t *testing.T) {
require.NoError(t, err)
logRecord.SetTimestamp(pcommon.NewTimestampFromTime(timestamp))

actual = newRFC5424Formatter().format(logRecord)
actual = newRFC5424Formatter(false).format(logRecord)
assert.Equal(t, expected, actual)
}

0 comments on commit e140374

Please sign in to comment.