diff --git a/logger.go b/logger.go index 2912ff0..3249c1a 100644 --- a/logger.go +++ b/logger.go @@ -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...)) } diff --git a/logger_test.go b/logger_test.go index b9f8a7e..530fb19 100644 --- a/logger_test.go +++ b/logger_test.go @@ -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()) +} diff --git a/pkg.go b/pkg.go index dd558a1..f3696cd 100644 --- a/pkg.go +++ b/pkg.go @@ -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. diff --git a/pkg_test.go b/pkg_test.go index e659343..d064cb9 100644 --- a/pkg_test.go +++ b/pkg_test.go @@ -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()) +} diff --git a/text.go b/text.go index 2e74db7..c428866 100644 --- a/text.go +++ b/text.go @@ -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) diff --git a/text_test.go b/text_test.go index a3b9666..7974e91 100644 --- a/text_test.go +++ b/text_test.go @@ -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()) +}