diff --git a/daemon/logger/journald/journald.go b/daemon/logger/journald/journald.go index 5e288eaaf7..9569859121 100644 --- a/daemon/logger/journald/journald.go +++ b/daemon/logger/journald/journald.go @@ -6,8 +6,8 @@ package journald import ( "fmt" - "strings" "sync" + "unicode" "github.com/Sirupsen/logrus" "github.com/coreos/go-systemd/journal" @@ -36,6 +36,26 @@ func init() { } } +// sanitizeKeyMode returns the sanitized string so that it could be used in journald. +// In journald log, there are special requirements for fields. +// Fields must be composed of uppercase letters, numbers, and underscores, but must +// not start with an underscore. +func sanitizeKeyMod(s string) string { + n := "" + for _, v := range s { + if 'a' <= v && v <= 'z' { + v = unicode.ToUpper(v) + } else if ('Z' < v || v < 'A') && ('9' < v || v < '0') { + v = '_' + } + // If (n == "" && v == '_'), then we will skip as this is the beginning with '_' + if !(n == "" && v == '_') { + n += string(v) + } + } + return n +} + // New creates a journald logger using the configuration passed in on // the context. func New(ctx logger.Context) (logger.Logger, error) { @@ -61,7 +81,7 @@ func New(ctx logger.Context) (logger.Logger, error) { "CONTAINER_NAME": name, "CONTAINER_TAG": tag, } - extraAttrs := ctx.ExtraAttributes(strings.ToTitle) + extraAttrs := ctx.ExtraAttributes(sanitizeKeyMod) for k, v := range extraAttrs { vars[k] = v } diff --git a/daemon/logger/journald/journald_test.go b/daemon/logger/journald/journald_test.go new file mode 100644 index 0000000000..224423fd07 --- /dev/null +++ b/daemon/logger/journald/journald_test.go @@ -0,0 +1,23 @@ +// +build linux + +package journald + +import ( + "testing" +) + +func TestSanitizeKeyMod(t *testing.T) { + entries := map[string]string{ + "io.kubernetes.pod.name": "IO_KUBERNETES_POD_NAME", + "io?.kubernetes.pod.name": "IO__KUBERNETES_POD_NAME", + "?io.kubernetes.pod.name": "IO_KUBERNETES_POD_NAME", + "io123.kubernetes.pod.name": "IO123_KUBERNETES_POD_NAME", + "_io123.kubernetes.pod.name": "IO123_KUBERNETES_POD_NAME", + "__io123_kubernetes.pod.name": "IO123_KUBERNETES_POD_NAME", + } + for k, v := range entries { + if sanitizeKeyMod(k) != v { + t.Fatalf("Failed to sanitize %s, got %s, expected %s", k, sanitizeKeyMod(k), v) + } + } +}