diff options
Diffstat (limited to '')
-rw-r--r-- | pkg/logging/journald_core.go | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/pkg/logging/journald_core.go b/pkg/logging/journald_core.go new file mode 100644 index 0000000..50dd39f --- /dev/null +++ b/pkg/logging/journald_core.go @@ -0,0 +1,85 @@ +package logging + +import ( + "github.com/icinga/icingadb/pkg/utils" + "github.com/pkg/errors" + "github.com/ssgreg/journald" + "go.uber.org/zap/zapcore" + "strings" + "unicode" +) + +// priorities maps zapcore.Level to journal.Priority. +var priorities = map[zapcore.Level]journald.Priority{ + zapcore.DebugLevel: journald.PriorityDebug, + zapcore.InfoLevel: journald.PriorityInfo, + zapcore.WarnLevel: journald.PriorityWarning, + zapcore.ErrorLevel: journald.PriorityErr, + zapcore.FatalLevel: journald.PriorityCrit, + zapcore.PanicLevel: journald.PriorityCrit, + zapcore.DPanicLevel: journald.PriorityCrit, +} + +// NewJournaldCore returns a zapcore.Core that sends log entries to systemd-journald and +// uses the given identifier as a prefix for structured logging context that is sent as journal fields. +func NewJournaldCore(identifier string, enab zapcore.LevelEnabler) zapcore.Core { + return &journaldCore{ + LevelEnabler: enab, + identifier: identifier, + identifierU: strings.ToUpper(identifier), + } +} + +type journaldCore struct { + zapcore.LevelEnabler + context []zapcore.Field + identifier string + identifierU string +} + +func (c *journaldCore) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry { + if c.Enabled(ent.Level) { + return ce.AddCore(ent, c) + } + + return ce +} + +func (c *journaldCore) Sync() error { + return nil +} + +func (c *journaldCore) With(fields []zapcore.Field) zapcore.Core { + cc := *c + cc.context = append(cc.context[:len(cc.context):len(cc.context)], fields...) + + return &cc +} + +func (c *journaldCore) Write(ent zapcore.Entry, fields []zapcore.Field) error { + pri, ok := priorities[ent.Level] + if !ok { + return errors.Errorf("unknown log level %q", ent.Level) + } + + enc := zapcore.NewMapObjectEncoder() + c.addFields(enc, fields) + c.addFields(enc, c.context) + enc.Fields["SYSLOG_IDENTIFIER"] = c.identifier + + message := ent.Message + if ent.LoggerName != c.identifier { + message = ent.LoggerName + ": " + message + } + + return journald.Send(message, pri, enc.Fields) +} + +func (c *journaldCore) addFields(enc zapcore.ObjectEncoder, fields []zapcore.Field) { + for _, field := range fields { + field.Key = c.identifierU + + "_" + + utils.ConvertCamelCase(field.Key, unicode.UpperCase, '_') + field.AddTo(enc) + } +} |