Skip to content

Commit

Permalink
feat: expose log function (#95)
Browse files Browse the repository at this point in the history
Exposing `logger.Log` makes it possible to use a custom log level to log
messages. Simply define a new level and use `Log` and `Logf` to log
messages using the newly defined level.

Fixes: #89
aymanbagabas authored Dec 7, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 64e865d commit 2338a13
Showing 6 changed files with 88 additions and 33 deletions.
35 changes: 21 additions & 14 deletions logger.go
Original file line number Diff line number Diff line change
@@ -49,7 +49,13 @@ type Logger struct {
styles *Styles
}

func (l *Logger) log(level Level, msg interface{}, keyvals ...interface{}) {
// Logf logs a message with formatting.
func (l *Logger) Logf(level Level, format string, args ...interface{}) {
l.Log(level, fmt.Sprintf(format, args...))
}

// Log logs the given message with the given keyvals for the given level.
func (l *Logger) Log(level Level, msg interface{}, keyvals ...interface{}) {
if atomic.LoadUint32(&l.isDiscard) != 0 {
return
}
@@ -83,7 +89,8 @@ func (l *Logger) handle(level Level, ts time.Time, frames []runtime.Frame, msg i
kvs = append(kvs, TimestampKey, ts)
}

if level != noLevel {
_, ok := l.styles.Levels[level]
if ok {
kvs = append(kvs, LevelKey, level)
}

@@ -343,62 +350,62 @@ func (l *Logger) WithPrefix(prefix string) *Logger {

// Debug prints a debug message.
func (l *Logger) Debug(msg interface{}, keyvals ...interface{}) {
l.log(DebugLevel, msg, keyvals...)
l.Log(DebugLevel, msg, keyvals...)
}

// Info prints an info message.
func (l *Logger) Info(msg interface{}, keyvals ...interface{}) {
l.log(InfoLevel, msg, keyvals...)
l.Log(InfoLevel, msg, keyvals...)
}

// Warn prints a warning message.
func (l *Logger) Warn(msg interface{}, keyvals ...interface{}) {
l.log(WarnLevel, msg, keyvals...)
l.Log(WarnLevel, msg, keyvals...)
}

// Error prints an error message.
func (l *Logger) Error(msg interface{}, keyvals ...interface{}) {
l.log(ErrorLevel, msg, keyvals...)
l.Log(ErrorLevel, msg, keyvals...)
}

// Fatal prints a fatal message and exits.
func (l *Logger) Fatal(msg interface{}, keyvals ...interface{}) {
l.log(FatalLevel, msg, keyvals...)
l.Log(FatalLevel, msg, keyvals...)
os.Exit(1)
}

// Print prints a message with no level.
func (l *Logger) Print(msg interface{}, keyvals ...interface{}) {
l.log(noLevel, msg, keyvals...)
l.Log(noLevel, msg, keyvals...)
}

// Debugf prints a debug message with formatting.
func (l *Logger) Debugf(format string, args ...interface{}) {
l.log(DebugLevel, fmt.Sprintf(format, args...))
l.Log(DebugLevel, fmt.Sprintf(format, args...))
}

// Infof prints an info message with formatting.
func (l *Logger) Infof(format string, args ...interface{}) {
l.log(InfoLevel, fmt.Sprintf(format, args...))
l.Log(InfoLevel, fmt.Sprintf(format, args...))
}

// Warnf prints a warning message with formatting.
func (l *Logger) Warnf(format string, args ...interface{}) {
l.log(WarnLevel, fmt.Sprintf(format, args...))
l.Log(WarnLevel, fmt.Sprintf(format, args...))
}

// Errorf prints an error message with formatting.
func (l *Logger) Errorf(format string, args ...interface{}) {
l.log(ErrorLevel, fmt.Sprintf(format, args...))
l.Log(ErrorLevel, fmt.Sprintf(format, args...))
}

// Fatalf prints a fatal message with formatting and exits.
func (l *Logger) Fatalf(format string, args ...interface{}) {
l.log(FatalLevel, fmt.Sprintf(format, args...))
l.Log(FatalLevel, fmt.Sprintf(format, args...))
os.Exit(1)
}

// Printf prints a message with no level and formatting.
func (l *Logger) Printf(format string, args ...interface{}) {
l.log(noLevel, fmt.Sprintf(format, args...))
l.Log(noLevel, fmt.Sprintf(format, args...))
}
13 changes: 11 additions & 2 deletions logger_test.go
Original file line number Diff line number Diff line change
@@ -257,12 +257,21 @@ func TestRace(t *testing.T) {
l.GetPrefix()

o := l.With("foo", "bar")
o.Print("foo")
o.Printf("foo %s", "bar")
o.SetTimeFormat(time.Kitchen)
o.Debug("foo")
o.Warn("foo")
o.SetOutput(w)
o.Error("foo")
o.SetFormatter(JSONFormatter)
})
}
}

func TestCustomLevel(t *testing.T) {
var buf bytes.Buffer
level500 := Level(500)
l := New(&buf)
l.SetLevel(level500)
l.Logf(level500, "foo")
assert.Equal(t, "foo\n", buf.String())
}
34 changes: 22 additions & 12 deletions pkg.go
Original file line number Diff line number Diff line change
@@ -160,66 +160,76 @@ func Helper() {
defaultLogger.helper(1)
}

// Log logs a message with the given level.
func Log(level Level, msg interface{}, keyvals ...interface{}) {
defaultLogger.Log(level, msg, keyvals...)
}

// Debug logs a debug message.
func Debug(msg interface{}, keyvals ...interface{}) {
defaultLogger.log(DebugLevel, msg, keyvals...)
defaultLogger.Log(DebugLevel, msg, keyvals...)
}

// Info logs an info message.
func Info(msg interface{}, keyvals ...interface{}) {
defaultLogger.log(InfoLevel, msg, keyvals...)
defaultLogger.Log(InfoLevel, msg, keyvals...)
}

// Warn logs a warning message.
func Warn(msg interface{}, keyvals ...interface{}) {
defaultLogger.log(WarnLevel, msg, keyvals...)
defaultLogger.Log(WarnLevel, msg, keyvals...)
}

// Error logs an error message.
func Error(msg interface{}, keyvals ...interface{}) {
defaultLogger.log(ErrorLevel, msg, keyvals...)
defaultLogger.Log(ErrorLevel, msg, keyvals...)
}

// Fatal logs a fatal message and exit.
func Fatal(msg interface{}, keyvals ...interface{}) {
defaultLogger.log(FatalLevel, msg, keyvals...)
defaultLogger.Log(FatalLevel, msg, keyvals...)
os.Exit(1)
}

// Print logs a message with no level.
func Print(msg interface{}, keyvals ...interface{}) {
defaultLogger.log(noLevel, msg, keyvals...)
defaultLogger.Log(noLevel, msg, keyvals...)
}

// Logf logs a message with formatting and level.
func Logf(level Level, format string, args ...interface{}) {
defaultLogger.Logf(level, format, args...)
}

// Debugf logs a debug message with formatting.
func Debugf(format string, args ...interface{}) {
defaultLogger.log(DebugLevel, fmt.Sprintf(format, args...))
defaultLogger.Log(DebugLevel, fmt.Sprintf(format, args...))
}

// Infof logs an info message with formatting.
func Infof(format string, args ...interface{}) {
defaultLogger.log(InfoLevel, fmt.Sprintf(format, args...))
defaultLogger.Log(InfoLevel, fmt.Sprintf(format, args...))
}

// Warnf logs a warning message with formatting.
func Warnf(format string, args ...interface{}) {
defaultLogger.log(WarnLevel, fmt.Sprintf(format, args...))
defaultLogger.Log(WarnLevel, fmt.Sprintf(format, args...))
}

// Errorf logs an error message with formatting.
func Errorf(format string, args ...interface{}) {
defaultLogger.log(ErrorLevel, fmt.Sprintf(format, args...))
defaultLogger.Log(ErrorLevel, fmt.Sprintf(format, args...))
}

// Fatalf logs a fatal message with formatting and exit.
func Fatalf(format string, args ...interface{}) {
defaultLogger.log(FatalLevel, fmt.Sprintf(format, args...))
defaultLogger.Log(FatalLevel, fmt.Sprintf(format, args...))
os.Exit(1)
}

// Printf logs a message with formatting and no level.
func Printf(format string, args ...interface{}) {
defaultLogger.log(noLevel, fmt.Sprintf(format, args...))
defaultLogger.Log(noLevel, fmt.Sprintf(format, args...))
}

// StandardLog returns a standard logger from the default logger.
19 changes: 16 additions & 3 deletions pkg_test.go
Original file line number Diff line number Diff line change
@@ -185,12 +185,12 @@ func TestGetLevel(t *testing.T) {
func TestPrefix(t *testing.T) {
var buf bytes.Buffer
SetOutput(&buf)
SetLevel(InfoLevel)
SetLevel(WarnLevel)
SetReportCaller(false)
SetReportTimestamp(false)
SetPrefix("prefix")
Info("info")
assert.Equal(t, "INFO prefix: info\n", buf.String())
Warn("info")
assert.Equal(t, "WARN prefix: info\n", buf.String())
assert.Equal(t, "prefix", GetPrefix())
SetPrefix("")
}
@@ -210,3 +210,16 @@ func TestWithPrefix(t *testing.T) {
l := WithPrefix("test")
assert.Equal(t, "test", l.prefix)
}

func TestGlobalCustomLevel(t *testing.T) {
var buf bytes.Buffer
lvl := Level(-1)
SetOutput(&buf)
SetLevel(lvl)
SetReportCaller(false)
SetReportTimestamp(false)
SetFormatter(JSONFormatter)
Log(lvl, "info")
Logf(lvl, "hey %s", "you")
assert.Equal(t, "{\"msg\":\"info\"}\n{\"msg\":\"hey you\"}\n", buf.String())
}
7 changes: 5 additions & 2 deletions text.go
Original file line number Diff line number Diff line change
@@ -183,9 +183,12 @@ func (l *Logger) textFormatter(keyvals ...interface{}) {
case LevelKey:
if level, ok := keyvals[i+1].(Level); ok {
var lvl string
if lvlStyle, ok := st.Levels[level]; ok {
lvl = lvlStyle.Renderer(l.re).String()
lvlStyle, ok := st.Levels[level]
if !ok {
continue
}

lvl = lvlStyle.Renderer(l.re).String()
if lvl != "" {
writeSpace(&l.b, firstKey)
l.b.WriteString(lvl)
13 changes: 13 additions & 0 deletions text_test.go
Original file line number Diff line number Diff line change
@@ -230,6 +230,7 @@ func TestTextFatal(t *testing.T) {
logger.SetReportCaller(true)
if os.Getenv("FATAL") == "1" {
logger.Fatal("i'm dead")
logger.Fatalf("bye %s", "bye")
return
}
cmd := exec.Command(os.Args[0], "-test.run=TestTextFatal")
@@ -421,3 +422,15 @@ func TestColorProfile(t *testing.T) {
assert.Equal(t, p, l.re.ColorProfile())
}
}

func TestCustomLevelStyle(t *testing.T) {
var buf bytes.Buffer
l := New(&buf)
st := DefaultStyles()
lvl := Level(1234)
st.Levels[lvl] = lipgloss.NewStyle().Bold(true).SetString("FUNKY")
l.SetStyles(st)
l.SetLevel(lvl)
l.Log(lvl, "foobar")
assert.Equal(t, "FUNKY foobar\n", buf.String())
}

0 comments on commit 2338a13

Please sign in to comment.