Skip to content

Commit

Permalink
feat: add stdlog writer
Browse files Browse the repository at this point in the history
  • Loading branch information
aymanbagabas committed Jan 8, 2023
1 parent be6879f commit f483102
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 9 deletions.
2 changes: 2 additions & 0 deletions logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ type Logger interface {
// Error logs an error message.
Error(msg interface{}, keyval ...interface{})

// StandardLoggerWriter returns a io.Writer that can be used along with the
StandardLoggerWriter(...StandardLoggerOption) io.Writer
// StandardLogger returns a standard logger from this logger.
StandardLogger(...StandardLoggerOption) *log.Logger
}
26 changes: 17 additions & 9 deletions stdlog.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package log

import (
"io"
"log"
"strings"
)

type stdLogger struct {
type stdLoggerWriter struct {
l *logger
opt *StandardLoggerOption
}

func (l *stdLogger) Write(p []byte) (n int, err error) {
func (l *stdLoggerWriter) Write(p []byte) (n int, err error) {
str := strings.TrimSuffix(string(p), "\n")

if l.opt != nil {
Expand Down Expand Up @@ -44,24 +45,31 @@ func (l *stdLogger) Write(p []byte) (n int, err error) {
return len(p), nil
}

// StandardLoggerOption can be used to configure the standard log addapter.
// StandardLoggerOption can be used to configure the standard log adapter.
type StandardLoggerOption struct {
ForceLevel Level
}

// StandardLogger returns a standard logger from Logger. The returned logger
// can infer log levels from message prefix. Expected prefixes are DEBUG, INFO,
// WARN, ERROR, and ERR.
func (l *logger) StandardLogger(opts ...StandardLoggerOption) *log.Logger {
// StandardLoggerWriter is a io.Writer that can be used along with the standard
// log library. The writer can infer log levels from message prefix. Expected
// prefixes are DEBUG, INFO, WARN, ERROR, and ERR.
func (l *logger) StandardLoggerWriter(opts ...StandardLoggerOption) io.Writer {
nl := *l
// The caller stack is
// log.Printf() -> l.Output() -> l.out.Write(stdLogger.Write)
nl.callerOffset += 3
sl := &stdLogger{
sl := &stdLoggerWriter{
l: &nl,
}
if len(opts) > 0 {
sl.opt = &opts[0]
}
return log.New(sl, "", 0)
return sl
}

// StandardLogger returns a standard logger from Logger. The returned logger
// can infer log levels from message prefix. Expected prefixes are DEBUG, INFO,
// WARN, ERROR, and ERR.
func (l *logger) StandardLogger(opts ...StandardLoggerOption) *log.Logger {
return log.New(l.StandardLoggerWriter(opts...), "", 0)
}
34 changes: 34 additions & 0 deletions stdlog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,37 @@ func TestStdLog_forceLevel(t *testing.T) {
})
}
}

func TestStdLog_writer(t *testing.T) {
var buf bytes.Buffer
logger := New(WithOutput(&buf), WithCaller(), WithNoStyles())
cases := []struct {
name string
expected string
level Level
}{
{
name: "debug",
expected: "",
level: DebugLevel,
},
{
name: "info",
expected: "INFO <log/stdlog_test.go:112> coffee\n",
level: InfoLevel,
},
{
name: "error",
expected: "ERROR <log/stdlog_test.go:112> coffee\n",
level: ErrorLevel,
},
}
for _, c := range cases {
buf.Reset()
t.Run(c.name, func(t *testing.T) {
l := log.New(logger.StandardLoggerWriter(StandardLoggerOption{ForceLevel: c.level}), "", 0)
l.Print("coffee")
assert.Equal(t, c.expected, buf.String())
})
}
}

0 comments on commit f483102

Please sign in to comment.