From 7581cf96fbe0cddacf246f2982634190ebe455c9 Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Thu, 7 Apr 2016 06:03:28 +0000 Subject: [PATCH] Additional syslog-format option to allow microsecond resolution in syslog timestamp. This fix tries to add an additional syslog-format of `rfc5424micro` which follows the same as rfc5424 except that it use microsecond resolution for timestamp. The purpose is to solve the issue raised in #21793 where log events might lose its ordering if happens on the same second. The timestamp field in rfc5424 is derived from rfc3339, though the maximium resolution is limited to "TIME-SECFRAC" which is 6 (microsecond resolution). The appropriate documentation (`docs/admin/logging/overview.md`) has been updated to reflect the change in this fix. This fix adds a unit test to cover the newly introduced format. This fix fixes #21793. Signed-off-by: Yong Tang --- daemon/logger/syslog/syslog.go | 15 ++++++++++++++- daemon/logger/syslog/syslog_test.go | 6 ++++++ docs/admin/logging/overview.md | 5 +++-- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/daemon/logger/syslog/syslog.go b/daemon/logger/syslog/syslog.go index 99e03278ce..088a31eb5e 100644 --- a/daemon/logger/syslog/syslog.go +++ b/daemon/logger/syslog/syslog.go @@ -76,9 +76,20 @@ func rfc5424formatterWithAppNameAsTag(p syslog.Priority, hostname, tag, content return msg } +// The timestamp field in rfc5424 is derived from rfc3339. Whereas rfc3339 makes allowances +// for multiple syntaxes, there are further restrictions in rfc5424, i.e., the maximium +// resolution is limited to "TIME-SECFRAC" which is 6 (microsecond resolution) +func rfc5424microformatterWithAppNameAsTag(p syslog.Priority, hostname, tag, content string) string { + timestamp := time.Now().Format("2006-01-02T15:04:05.999999Z07:00") + pid := os.Getpid() + msg := fmt.Sprintf("<%d>%d %s %s %s %d %s %s", + p, 1, timestamp, hostname, tag, pid, tag, content) + return msg +} + // New creates a syslog logger using the configuration passed in on // the context. Supported context configuration variables are -// syslog-address, syslog-facility, & syslog-tag. +// syslog-address, syslog-facility, syslog-format, syslog-tag. func New(ctx logger.Context) (logger.Logger, error) { tag, err := loggerutils.ParseLogTag(ctx, "{{.ID}}") if err != nil { @@ -240,6 +251,8 @@ func parseLogFormat(logFormat string) (syslog.Formatter, syslog.Framer, error) { return syslog.RFC3164Formatter, syslog.DefaultFramer, nil case "rfc5424": return rfc5424formatterWithAppNameAsTag, syslog.RFC5425MessageLengthFramer, nil + case "rfc5424micro": + return rfc5424microformatterWithAppNameAsTag, syslog.RFC5425MessageLengthFramer, nil default: return nil, nil, errors.New("Invalid syslog format") } diff --git a/daemon/logger/syslog/syslog_test.go b/daemon/logger/syslog/syslog_test.go index c18494be10..f083030b70 100644 --- a/daemon/logger/syslog/syslog_test.go +++ b/daemon/logger/syslog/syslog_test.go @@ -19,6 +19,12 @@ func TestParseLogFormat(t *testing.T) { t.Fatal("Failed to parse rfc5424 format", err, formatter, framer) } + formatter, framer, err = parseLogFormat("rfc5424micro") + if err != nil || !functionMatches(rfc5424microformatterWithAppNameAsTag, formatter) || + !functionMatches(syslog.RFC5425MessageLengthFramer, framer) { + t.Fatal("Failed to parse rfc5424 (microsecond) format", err, formatter, framer) + } + formatter, framer, err = parseLogFormat("rfc3164") if err != nil || !functionMatches(syslog.RFC3164Formatter, formatter) || !functionMatches(syslog.DefaultFramer, framer) { diff --git a/docs/admin/logging/overview.md b/docs/admin/logging/overview.md index 8a7cd12ffb..c3c6e15f8e 100644 --- a/docs/admin/logging/overview.md +++ b/docs/admin/logging/overview.md @@ -80,7 +80,7 @@ The following logging options are supported for the `syslog` logging driver: --log-opt syslog-tls-key=/etc/ca-certificates/custom/key.pem --log-opt syslog-tls-skip-verify=true --log-opt tag="mailer" - --log-opt syslog-format=[rfc5424|rfc3164] + --log-opt syslog-format=[rfc5424|rfc5424micro|rfc3164] `syslog-address` specifies the remote syslog server address where the driver connects to. If not specified it defaults to the local unix socket of the running system. @@ -135,7 +135,8 @@ the log tag format. `syslog-format` specifies syslog message format to use when logging. If not specified it defaults to the local unix syslog format without hostname specification. Specify rfc3164 to perform logging in RFC-3164 compatible format. Specify rfc5424 to perform -logging in RFC-5424 compatible format +logging in RFC-5424 compatible format. Specify rfc5424micro to perform logging in RFC-5424 +compatible format with microsecond timestamp resolution. ## journald options