diff --git a/go.mod b/go.mod index 2fa1a8d..e49c88f 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,15 @@ module r00t2.io/goutils -go 1.16 +go 1.24.5 require ( - github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf - github.com/google/uuid v1.3.0 - golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e - r00t2.io/sysutils v1.1.1 + github.com/coreos/go-systemd/v22 v22.5.0 + github.com/google/uuid v1.6.0 + golang.org/x/sys v0.34.0 + r00t2.io/sysutils v1.14.0 +) + +require ( + github.com/djherbis/times v1.6.0 // indirect + golang.org/x/sync v0.16.0 // indirect ) diff --git a/go.sum b/go.sum index 44ee240..44b4a32 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,12 @@ -github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= -github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -r00t2.io/sysutils v1.1.1 h1:q2P5u50HIIRk6muCPo1Gpapy6sNT4oaB1l2O/C/mi3A= -r00t2.io/sysutils v1.1.1/go.mod h1:Wlfi1rrJpoKBOjWiYM9rw2FaiZqraD6VpXyiHgoDo/o= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= +github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= +golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= diff --git a/iox/docs.go b/iox/docs.go new file mode 100644 index 0000000..a1c3bf1 --- /dev/null +++ b/iox/docs.go @@ -0,0 +1,4 @@ +/* +Package iox includes extensions to the stdlib `io` module. +*/ +package iox diff --git a/iox/errs.go b/iox/errs.go new file mode 100644 index 0000000..659357c --- /dev/null +++ b/iox/errs.go @@ -0,0 +1,9 @@ +package iox + +import ( + `errors` +) + +var ( + ErrBufTooSmall error = errors.New("buffer too small; buffer size must be > 0") +) diff --git a/iox/funcs.go b/iox/funcs.go new file mode 100644 index 0000000..9104c48 --- /dev/null +++ b/iox/funcs.go @@ -0,0 +1,41 @@ +package iox + +import ( + `io` +) + +/* +CopyBufN is a mix between io.CopyN and io.CopyBuffer. + +Despite what the docs may suggest, io.CopyN does NOT *read* n bytes from src AND write n bytes to dst. +Instead, it always reads 32 KiB from src, and writes n bytes to dst. + +There are, of course, cases where this is deadfully undesired. + +One can, of course, use io.CopyBuffer, but this is a bit annoying since you then have to provide a buffer yourself. + +This convenience-wraps io.CopyBuffer to have a similar signature to io.CopyN but properly uses n for both reading and writing. +*/ +func CopyBufN(dst io.Writer, src io.Reader, n int64) (written int64, err error) { + + var b []byte + + if n <= 0 { + err = ErrBufTooSmall + return + } + + b = make([]byte, n) + + written, err = io.CopyBuffer(dst, src, b) + + return +} + +// CopyBufWith allows for specifying a buffer allocator function, otherwise acts as CopyBufN. +func CopyBufWith(dst io.Writer, src io.Reader, bufFunc func() (b []byte)) (written int64, err error) { + + written, err = io.CopyBuffer(dst, src, bufFunc()) + + return +} diff --git a/iox/types.go b/iox/types.go new file mode 100644 index 0000000..7f92ca1 --- /dev/null +++ b/iox/types.go @@ -0,0 +1,8 @@ +package iox + +type ( + // RuneWriter matches the behavior of *(bytes.Buffer).WriteRune and *(bufio.Writer).WriteRune + RuneWriter interface { + WriteRune(r rune) (n int, err error) + } +) diff --git a/logging/TODO b/logging/TODO index 89b356f..abc06b1 100644 --- a/logging/TODO +++ b/logging/TODO @@ -4,19 +4,20 @@ -- no native Go support (yet)? --- https://developer.apple.com/forums/thread/773369 +- add a `log/slog` logging.Logger? + - Implement code line/func/etc. (only for debug?): https://stackoverflow.com/a/24809646 https://golang.org/pkg/runtime/#Caller -- log.LlongFile and log.Lshortfile flags don't currently work properly for StdLogger/FileLogger; they refer to the file in logging package rather than the caller. + -- ZeroLog seems to be able to do it, take a peek there. - StdLogger2; where stdout and stderr are both logged to depending on severity level. - make configurable via OR bitmask -- Suport remote loggers? (eventlog, syslog, systemd) +- Suport remote loggers? (eventlog, syslog, journald) - JSON logger? YAML logger? XML logger? - DOCS. -- Done, but flesh out. - -- Implement io.Writer interfaces diff --git a/logging/doc.go b/logging/doc.go index 44fc129..2943d08 100644 --- a/logging/doc.go +++ b/logging/doc.go @@ -11,9 +11,12 @@ These particular loggers (logging.Logger) available are: WinLogger (Windows only) There is a seventh type of logging.Logger, MultiLogger, that allows for multiple loggers to be written to with a single call. -As you may have guessed, NullLogger doesn't actually log anything but is fully "functional" as a logging.Logger. +(This is similar to stdlib's io.MultiWriter()'s return value, but with priority awareness and fmt string support). -Note that for some Loggers, the prefix may be modified - "literal" loggers (StdLogger and FileLogger) will append a space to the end of the prefix. +As you may have guessed, NullLogger doesn't actually log anything but is fully "functional" as a logging.Logger (similar to io.discard/io.Discard()'s return). + +Note that for some Loggers, the prefix may be modified after the Logger has already initialized. +"Literal" loggers (StdLogger and FileLogger) will append a space to the end of the prefix by default. If this is undesired (unlikely), you will need to modify (Logger).Prefix and run (Logger).Logger.SetPrefix(yourPrefixHere) for the respective logger. Every logging.Logger type has the following methods that correspond to certain "levels". @@ -45,5 +48,17 @@ logging.Logger types also have the following methods: In some cases, Logger.Setup and Logger.Shutdown are no-ops. In other cases, they perform necessary initialization/cleanup and closing of the logger. It is recommended to *always* run Setup and Shutdown before and after using, respectively, regardless of the actual logging.Logger type. + +Lastly, all logging.Loggers have a ToLogger() method. This returns a *log.Logger (from stdlib log), which also conforms to io.Writer inherently. +In addition. all have a ToRaw() method, which extends a Logger even further and returns an unexported type (*logging.logWriter) compatible with: + + - io.ByteWriter + - io.Writer + - io.WriteCloser (Shutdown() on the Logger backend is called during Close(), rendering the underlying Logger unsafe to use afterwards) + - io.StringWriter + +and, if stdlib io ever defines an e.g. RuneWriter (WriteRune(r rune) (n int, err error)), it will conform to that too (see (r00t2.io/goutils/iox).RuneWriter). +Obviously this and io.ByteWriter are fairly silly, as they're intended to be high-speed throughput-optimized methods, but if you wanted to e.g. +log every single byte on a wire as a separate log message, go ahead; I'm not your dad. */ package logging diff --git a/logging/errs.go b/logging/errs.go index cc441c5..1f7ceb0 100644 --- a/logging/errs.go +++ b/logging/errs.go @@ -1,7 +1,7 @@ package logging import ( - `errors` + "errors" ) var ( @@ -12,6 +12,8 @@ var ( exists with too restrictive perms to write/append to, and/or could not be created. */ ErrInvalidFile error = errors.New("a FileLogger was requested but the file does not exist and cannot be created") + // ErrInvalidRune is returned if a rune was expected but it is not a valid UTF-8 codepoint. + ErrInvalidRune error = errors.New("specified rune is not valid UTF-8 codepoint") // ErrNoEntry indicates that the user attempted to MultiLogger.RemoveLogger a Logger but one by that identifier does not exist. ErrNoEntry error = errors.New("the Logger specified to be removed does not exist") ) diff --git a/logging/funcs.go b/logging/funcs.go index 641b53d..1b3fad9 100644 --- a/logging/funcs.go +++ b/logging/funcs.go @@ -1,9 +1,33 @@ package logging import ( + "log" "os" ) +/* +ToLog returns a stdlib *log.Logger from a logging.Logger. It simply wraps the (logging.Logger).ToLogger() methods. + +prio is an OR'd logPrio of the Priority* constants. +*/ +func ToLog(l Logger, prio logPrio) (stdLibLog *log.Logger) { + + stdLibLog = l.ToLogger(prio) + + return +} + +// ToRaw returns a *logWriter from a logging.Logger. It is an alternative to the (logging.Logger).ToRaw() methods. +func ToRaw(l Logger, prio logPrio) (raw *logWriter) { + + raw = &logWriter{ + backend: l, + prio: prio, + } + + return +} + // testOpen attempts to open a file for writing to test for suitability as a LogFile path. func testOpen(path string) (success bool, err error) { diff --git a/logging/funcs_file.go b/logging/funcs_file.go index ea556c9..f693788 100644 --- a/logging/funcs_file.go +++ b/logging/funcs_file.go @@ -223,7 +223,15 @@ func (l *FileLogger) Warning(s string, v ...interface{}) (err error) { // ToLogger returns a stdlib log.Logger. func (l *FileLogger) ToLogger(prio logPrio) (stdLibLog *log.Logger) { - stdLibLog = log.New(&logWriter{backend: l, prio: prio}, "", 0) + stdLibLog = log.New(l.ToRaw(prio), "", 0) + + return +} + +// ToRaw returns a *logWriter. +func (l *FileLogger) ToRaw(prio logPrio) (raw *logWriter) { + + raw = &logWriter{backend: l, prio: prio} return } diff --git a/logging/funcs_linux.go b/logging/funcs_linux.go index e849f50..e93ad2f 100644 --- a/logging/funcs_linux.go +++ b/logging/funcs_linux.go @@ -5,7 +5,7 @@ import ( `os` `path` - sysd `github.com/coreos/go-systemd/journal` + sysd `github.com/coreos/go-systemd/v22/journal` `r00t2.io/goutils/bitmask` `r00t2.io/sysutils/paths` ) diff --git a/logging/funcs_logwriter.go b/logging/funcs_logwriter.go index b4d7b64..862266f 100644 --- a/logging/funcs_logwriter.go +++ b/logging/funcs_logwriter.go @@ -1,10 +1,34 @@ package logging import ( - `r00t2.io/goutils/multierr` + "unicode/utf8" + + "r00t2.io/goutils/multierr" ) -// Write writes bytes b to the underlying Logger's priority level if the logWriter's priority level(s) match. +/* +Close calls Logger.Shutdown() on the underlying Logger. +The Logger *must not be used* after this; it will need to be re-initialized with Logger.Setup() +or a new Logger (and thuse new logWriter) must be created to replace it. + +It (along with logWriter.Write()) conforms to WriteCloser(). +*/ +func (l *logWriter) Close() (err error) { + + if err = l.backend.Shutdown(); err != nil { + return + } + + return +} + +/* +Write writes bytes b to the underlying Logger's priority level if the logWriter's priority level(s) match. +It conforms to io.Writer. n will *always* == len(b) on success, because otherwise n would technically be >= len(b) +(if multiple priorities are enabled), which is undefined behavior per io.Writer. + +b is converted to a string to normalize to the underlying Logger. +*/ func (l *logWriter) Write(b []byte) (n int, err error) { var s string @@ -70,5 +94,116 @@ func (l *logWriter) Write(b []byte) (n int, err error) { return } + n = len(b) + + return +} + +/* +WriteByte conforms a logWriter to an io.ByteWriter. (It just wraps logWriter.Write().) +You should probably never use this; the logging overhead/prefix is going to be more data than the single byte itself. + +c is converted to a string to normalize to the underlying Logger. +*/ +func (l *logWriter) WriteByte(c byte) (err error) { + + if _, err = l.Write([]byte{c}); err != nil { + return + } + + return +} + +/* +WriteRune follows the same signature of (bytes.Buffer).WriteRune() and (bufio.Writer).WriteRune(); thus if `io` ever defines an io.RuneWriter interface, here ya go. + +n will *always* be equal to (unicode/utf8).RuneLen(r), unless r is an "invalid rune" -- in which case n will be 0 and err will be ErrInvalidRune.. +*/ +func (l *logWriter) WriteRune(r rune) (n int, err error) { + + var b []byte + + n = utf8.RuneLen(r) + if n < 0 { + err = ErrInvalidRune + n = 0 + return + } + + b = make([]byte, n) + utf8.EncodeRune(b, r) + + if n, err = l.Write(b); err != nil { + return + } + + return +} + +/* +WriteString writes string s to the underlying Logger's priority level if the logWriter's priority level(s) match. +It conforms to io.StringWriter. n will *always* == len(s) on success, because otherwise n would technically be >= len(s) +(if multiple priorities are enabled), which is undefined behavior per io.StringWriter. +*/ +func (l *logWriter) WriteString(s string) (n int, err error) { + + var mErr *multierr.MultiError = multierr.NewMultiError(nil) + + 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 + } + + n = len(s) + return } diff --git a/logging/funcs_multilogger.go b/logging/funcs_multilogger.go index a349708..acc67e7 100644 --- a/logging/funcs_multilogger.go +++ b/logging/funcs_multilogger.go @@ -3,7 +3,7 @@ package logging import ( "errors" "fmt" - `log` + "log" "sync" "r00t2.io/goutils/multierr" @@ -375,7 +375,15 @@ func (m *MultiLogger) Warning(s string, v ...interface{}) (err error) { // ToLogger returns a stdlib log.Logger. func (m *MultiLogger) ToLogger(prio logPrio) (stdLibLog *log.Logger) { - stdLibLog = log.New(&logWriter{backend: m, prio: prio}, "", 0) + stdLibLog = log.New(m.ToRaw(prio), "", 0) + + return +} + +// ToRaw returns a *logWriter. +func (m *MultiLogger) ToRaw(prio logPrio) (raw *logWriter) { + + raw = &logWriter{backend: m, prio: prio} return } diff --git a/logging/funcs_multilogger_mgr_linux.go b/logging/funcs_multilogger_mgr_linux.go index 0205b3b..1df484d 100644 --- a/logging/funcs_multilogger_mgr_linux.go +++ b/logging/funcs_multilogger_mgr_linux.go @@ -1,7 +1,7 @@ package logging import ( - sysd "github.com/coreos/go-systemd/journal" + sysd "github.com/coreos/go-systemd/v22/journal" "github.com/google/uuid" ) diff --git a/logging/funcs_nulllogger.go b/logging/funcs_nulllogger.go index d3e5850..8e324d0 100644 --- a/logging/funcs_nulllogger.go +++ b/logging/funcs_nulllogger.go @@ -1,7 +1,7 @@ package logging import ( - `log` + "log" ) // Setup does nothing at all; it's here for interface compat. 🙃 @@ -84,3 +84,11 @@ func (l *NullLogger) ToLogger(prio logPrio) (stdLibLog *log.Logger) { return } + +// ToRaw returns a *logWriter. (This is a little less efficient than using ToLogger's log.Logger as an io.Writer if that's all you need.) +func (l *NullLogger) ToRaw(prio logPrio) (raw *logWriter) { + + raw = &logWriter{backend: l, prio: prio} + + return +} diff --git a/logging/funcs_nullwriter.go b/logging/funcs_nullwriter.go index 4b2b2c8..c11df29 100644 --- a/logging/funcs_nullwriter.go +++ b/logging/funcs_nullwriter.go @@ -1,6 +1,18 @@ package logging -// nulLWriter writes... nothing. To avoid errors, however, in downstream code it pretends it does (n will *always* == len(b)). +import ( + "unicode/utf8" +) + +// Close conforms a nullWriter to an io.WriteCloser. It obviously does nothing, and will always return with err == nil. +func (nw *nullWriter) Close() (err error) { + + // NO-OP + + return +} + +// Write conforms a nullWriter to an io.Writer, but it 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 { @@ -10,3 +22,37 @@ func (nw *nullWriter) Write(b []byte) (n int, err error) { return } + +// WriteByte conforms to an io.ByteWriter but again... nothing is actually written anywhere. +func (nw *nullWriter) WriteByte(c byte) (err error) { + + // NO-OP + + _ = c + + return +} + +/* +WriteRune conforms to the other Loggers. It WILL return the proper value for n (matching (bytes.Buffer).WriteRune() and (bufio.Writer).WriteRune() signatures, +and it WILL return an ErrInvalidRune if r is not a valid rune, but otherwise it will no-op. +*/ +func (nw *nullWriter) WriteRune(r rune) (n int, err error) { + + n = utf8.RuneLen(r) + if n < 0 { + err = ErrInvalidRune + n = 0 + return + } + + return +} + +// WriteString conforms to an io.StringWriter but nothing is actually written. (n will *always* == len(s)) +func (nw *nullWriter) WriteString(s string) (n int, err error) { + + n = len(s) + + return +} diff --git a/logging/funcs_std.go b/logging/funcs_std.go index f7a16f3..e577c09 100644 --- a/logging/funcs_std.go +++ b/logging/funcs_std.go @@ -235,6 +235,22 @@ func (l *StdLogger) Warning(s string, v ...interface{}) (err error) { return } +// ToLogger returns a stdlib log.Logger. +func (l *StdLogger) ToLogger(prio logPrio) (stdLibLog *log.Logger) { + + stdLibLog = log.New(l.ToRaw(prio), "", 0) + + return +} + +// ToRaw returns a *logWriter. +func (l *StdLogger) ToRaw(prio logPrio) (raw *logWriter) { + + raw = &logWriter{backend: l, prio: prio} + + return +} + // renderWrite prepares/formats a log message to be written to this StdLogger. func (l *StdLogger) renderWrite(msg, prio string) { @@ -244,11 +260,3 @@ 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 2c06a76..857ea02 100644 --- a/logging/funcs_sysd_linux.go +++ b/logging/funcs_sysd_linux.go @@ -4,7 +4,7 @@ import ( "fmt" "log" - "github.com/coreos/go-systemd/journal" + "github.com/coreos/go-systemd/v22/journal" ) /* @@ -227,7 +227,15 @@ func (l *SystemDLogger) renderWrite(msg string, prio journal.Priority) { // ToLogger returns a stdlib log.Logger. func (l *SystemDLogger) ToLogger(prio logPrio) (stdLibLog *log.Logger) { - stdLibLog = log.New(&logWriter{backend: l, prio: prio}, "", 0) + stdLibLog = log.New(l.ToRaw(prio), "", 0) + + return +} + +// ToRaw returns a *logWriter. +func (l *SystemDLogger) ToRaw(prio logPrio) (raw *logWriter) { + + raw = &logWriter{backend: l, prio: prio} return } diff --git a/logging/funcs_syslog_nix.go b/logging/funcs_syslog_nix.go index e7e05dd..103a678 100644 --- a/logging/funcs_syslog_nix.go +++ b/logging/funcs_syslog_nix.go @@ -273,7 +273,15 @@ func (l *SyslogLogger) Warning(s string, v ...interface{}) (err error) { // ToLogger returns a stdlib log.Logger. func (l *SyslogLogger) ToLogger(prio logPrio) (stdLibLog *log.Logger) { - stdLibLog = log.New(&logWriter{backend: l, prio: prio}, "", 0) + stdLibLog = log.New(l.ToRaw(prio), "", 0) + + return +} + +// ToRaw returns a *logWriter. +func (l *SyslogLogger) ToRaw(prio logPrio) (raw *logWriter) { + + raw = &logWriter{backend: l, prio: prio} return } diff --git a/logging/funcs_winlogger_windows.go b/logging/funcs_winlogger_windows.go index 830b45b..d0c49f2 100644 --- a/logging/funcs_winlogger_windows.go +++ b/logging/funcs_winlogger_windows.go @@ -3,7 +3,7 @@ package logging import ( "errors" "fmt" - `log` + "log" "os" "os/exec" "syscall" @@ -347,7 +347,15 @@ func (l *WinLogger) Warning(s string, v ...interface{}) (err error) { // ToLogger returns a stdlib log.Logger. func (l *WinLogger) ToLogger(prio logPrio) (stdLibLog *log.Logger) { - stdLibLog = log.New(&logWriter{backend: l, prio: prio}, "", 0) + stdLibLog = log.New(l.ToRaw(prio), "", 0) + + return +} + +// ToRaw returns a *logWriter. +func (l *WinLogger) ToRaw(prio logPrio) (raw *logWriter) { + + raw = &logWriter{backend: l, prio: prio} return } diff --git a/logging/types.go b/logging/types.go index cb5745f..2abd29a 100644 --- a/logging/types.go +++ b/logging/types.go @@ -4,7 +4,7 @@ import ( "log" "os" - `r00t2.io/goutils/bitmask` + "r00t2.io/goutils/bitmask" ) type logPrio bitmask.MaskBit @@ -28,6 +28,7 @@ type Logger interface { Setup() (err error) Shutdown() (err error) ToLogger(prio logPrio) (stdLibLog *log.Logger) + ToRaw(prio logPrio) (raw *logWriter) } /*