diff --git a/logging/consts.go b/logging/consts.go index bd7f61e..5ad5b78 100644 --- a/logging/consts.go +++ b/logging/consts.go @@ -12,3 +12,16 @@ const ( // appendFlags are the flags used for testing the file (and opening/writing). appendFlags int = os.O_APPEND | os.O_CREATE | os.O_WRONLY ) + +const PriorityNone logPrio = 0 +const ( + PriorityEmergency logPrio = 1 << iota + PriorityAlert + PriorityCritical + PriorityError + PriorityWarning + PriorityNotice + PriorityInformational + PriorityDebug +) +const PriorityAll logPrio = PriorityEmergency | PriorityAlert | PriorityCritical | PriorityError | PriorityWarning | PriorityNotice | PriorityInformational | PriorityDebug diff --git a/logging/funcs_file.go b/logging/funcs_file.go index 0705b7d..ea556c9 100644 --- a/logging/funcs_file.go +++ b/logging/funcs_file.go @@ -220,6 +220,14 @@ func (l *FileLogger) Warning(s string, v ...interface{}) (err error) { return } +// ToLogger returns a stdlib log.Logger. +func (l *FileLogger) ToLogger(prio logPrio) (stdLibLog *log.Logger) { + + stdLibLog = log.New(&logWriter{backend: l, prio: prio}, "", 0) + + return +} + // renderWrite prepares/formats a log message to be written to this FileLogger. func (l *FileLogger) renderWrite(msg, prio string) { diff --git a/logging/funcs_logprio.go b/logging/funcs_logprio.go new file mode 100644 index 0000000..b3d32ab --- /dev/null +++ b/logging/funcs_logprio.go @@ -0,0 +1,23 @@ +package logging + +import ( + `r00t2.io/goutils/bitmask` +) + +// HasFlag provides a wrapper for functionality to the underlying bitmask.MaskBit. +func (l *logPrio) HasFlag(prio logPrio) (hasFlag bool) { + + var m *bitmask.MaskBit + var p *bitmask.MaskBit + + if l == nil { + return + } + + m = bitmask.NewMaskBitExplicit(uint(*l)) + p = bitmask.NewMaskBitExplicit(uint(prio)) + + hasFlag = m.HasFlag(*p) + + return +} diff --git a/logging/funcs_logwriter.go b/logging/funcs_logwriter.go new file mode 100644 index 0000000..b4d7b64 --- /dev/null +++ b/logging/funcs_logwriter.go @@ -0,0 +1,74 @@ +package logging + +import ( + `r00t2.io/goutils/multierr` +) + +// Write writes bytes b to the underlying Logger's priority level if the logWriter's priority level(s) match. +func (l *logWriter) Write(b []byte) (n int, err error) { + + var s string + var mErr *multierr.MultiError = multierr.NewMultiError(nil) + + if b == nil { + return + } + + s = string(b) + + if l.prio.HasFlag(PriorityEmergency) { + if err = l.backend.Emerg(s); err != nil { + mErr.AddError(err) + err = nil + } + } + if l.prio.HasFlag(PriorityAlert) { + if err = l.backend.Alert(s); err != nil { + mErr.AddError(err) + err = nil + } + } + if l.prio.HasFlag(PriorityCritical) { + if err = l.backend.Crit(s); err != nil { + mErr.AddError(err) + err = nil + } + } + if l.prio.HasFlag(PriorityError) { + if err = l.backend.Err(s); err != nil { + mErr.AddError(err) + err = nil + } + } + if l.prio.HasFlag(PriorityWarning) { + if err = l.backend.Warning(s); err != nil { + mErr.AddError(err) + err = nil + } + } + if l.prio.HasFlag(PriorityNotice) { + if err = l.backend.Notice(s); err != nil { + mErr.AddError(err) + err = nil + } + } + if l.prio.HasFlag(PriorityInformational) { + if err = l.backend.Info(s); err != nil { + mErr.AddError(err) + err = nil + } + } + if l.prio.HasFlag(PriorityDebug) { + if err = l.backend.Debug(s); err != nil { + mErr.AddError(err) + err = nil + } + } + + if !mErr.IsEmpty() { + err = mErr + return + } + + return +} diff --git a/logging/funcs_multilogger.go b/logging/funcs_multilogger.go index 39e349b..a349708 100644 --- a/logging/funcs_multilogger.go +++ b/logging/funcs_multilogger.go @@ -3,6 +3,7 @@ package logging import ( "errors" "fmt" + `log` "sync" "r00t2.io/goutils/multierr" @@ -370,3 +371,11 @@ func (m *MultiLogger) Warning(s string, v ...interface{}) (err error) { return } + +// ToLogger returns a stdlib log.Logger. +func (m *MultiLogger) ToLogger(prio logPrio) (stdLibLog *log.Logger) { + + stdLibLog = log.New(&logWriter{backend: m, prio: prio}, "", 0) + + return +} diff --git a/logging/funcs_nulllogger.go b/logging/funcs_nulllogger.go index 781388c..d3e5850 100644 --- a/logging/funcs_nulllogger.go +++ b/logging/funcs_nulllogger.go @@ -1,5 +1,9 @@ package logging +import ( + `log` +) + // Setup does nothing at all; it's here for interface compat. 🙃 func (l *NullLogger) Setup() (err error) { return @@ -72,3 +76,11 @@ func (l *NullLogger) Notice(s string, v ...interface{}) (err error) { func (l *NullLogger) Warning(s string, v ...interface{}) (err error) { return } + +// ToLogger returns a stdlib log.Logger (that doesn't actually write to anything). +func (l *NullLogger) ToLogger(prio logPrio) (stdLibLog *log.Logger) { + + stdLibLog = log.New(&nullWriter{}, "", 0) + + return +} diff --git a/logging/funcs_nullwriter.go b/logging/funcs_nullwriter.go new file mode 100644 index 0000000..4b2b2c8 --- /dev/null +++ b/logging/funcs_nullwriter.go @@ -0,0 +1,12 @@ +package logging + +// nulLWriter writes... nothing. To avoid errors, however, in downstream code it pretends it does (n will *always* == len(b)). +func (nw *nullWriter) Write(b []byte) (n int, err error) { + + if b == nil { + return + } + n = len(b) + + return +} diff --git a/logging/funcs_std.go b/logging/funcs_std.go index 99d5e7d..f7a16f3 100644 --- a/logging/funcs_std.go +++ b/logging/funcs_std.go @@ -244,3 +244,11 @@ func (l *StdLogger) renderWrite(msg, prio string) { return } + +// ToLogger returns a stdlib log.Logger. +func (l *StdLogger) ToLogger(prio logPrio) (stdLibLog *log.Logger) { + + stdLibLog = log.New(&logWriter{backend: l, prio: prio}, "", 0) + + return +} diff --git a/logging/funcs_sysd_linux.go b/logging/funcs_sysd_linux.go index ac5b7e2..2c06a76 100644 --- a/logging/funcs_sysd_linux.go +++ b/logging/funcs_sysd_linux.go @@ -223,3 +223,11 @@ func (l *SystemDLogger) renderWrite(msg string, prio journal.Priority) { return } + +// ToLogger returns a stdlib log.Logger. +func (l *SystemDLogger) ToLogger(prio logPrio) (stdLibLog *log.Logger) { + + stdLibLog = log.New(&logWriter{backend: l, prio: prio}, "", 0) + + return +} diff --git a/logging/funcs_syslog_linux.go b/logging/funcs_syslog_linux.go index 82960d6..a75d429 100644 --- a/logging/funcs_syslog_linux.go +++ b/logging/funcs_syslog_linux.go @@ -266,3 +266,11 @@ func (l *SyslogLogger) Warning(s string, v ...interface{}) (err error) { return } + +// ToLogger returns a stdlib log.Logger. +func (l *SyslogLogger) ToLogger(prio logPrio) (stdLibLog *log.Logger) { + + stdLibLog = log.New(&logWriter{backend: l, prio: prio}, "", 0) + + return +} diff --git a/logging/funcs_winlogger_windows.go b/logging/funcs_winlogger_windows.go index 0dc153d..830b45b 100644 --- a/logging/funcs_winlogger_windows.go +++ b/logging/funcs_winlogger_windows.go @@ -3,6 +3,7 @@ package logging import ( "errors" "fmt" + `log` "os" "os/exec" "syscall" @@ -342,3 +343,11 @@ func (l *WinLogger) Warning(s string, v ...interface{}) (err error) { return } + +// ToLogger returns a stdlib log.Logger. +func (l *WinLogger) ToLogger(prio logPrio) (stdLibLog *log.Logger) { + + stdLibLog = log.New(&logWriter{backend: l, prio: prio}, "", 0) + + return +} diff --git a/logging/types.go b/logging/types.go index d65c449..cb5745f 100644 --- a/logging/types.go +++ b/logging/types.go @@ -3,8 +3,12 @@ package logging import ( "log" "os" + + `r00t2.io/goutils/bitmask` ) +type logPrio bitmask.MaskBit + /* Logger is one of the various loggers offered by this module. */ @@ -23,6 +27,7 @@ type Logger interface { GetPrefix() (p string, err error) Setup() (err error) Shutdown() (err error) + ToLogger(prio logPrio) (stdLibLog *log.Logger) } /* @@ -105,3 +110,12 @@ type MultiLogger struct { */ Loggers map[string]Logger } + +// logWriter is used as a log.Logger and is returned by .ToLogger. +type logWriter struct { + backend Logger + prio logPrio +} + +// nullWriter is used as a shortcut by NullLogger.ToLogger. +type nullWriter struct{}