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) } }