From 4981d8161c238636b2ca8cf6b4e0d717716452ee Mon Sep 17 00:00:00 2001 From: drampull Date: Fri, 20 Oct 2017 08:40:54 -0400 Subject: [PATCH 1/5] Added TRACE level logging. --- .gitignore | 1 + entry.go | 18 ++++++++++++++++++ example_basic_test.go | 8 +++++++- exported.go | 15 +++++++++++++++ hook_test.go | 2 ++ hooks/syslog/syslog.go | 2 +- logger.go | 24 ++++++++++++++++++++++++ logrus.go | 10 ++++++++++ text_formatter.go | 2 +- writer.go | 2 ++ 10 files changed, 81 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 66be63a..6b7d7d1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ logrus +vendor diff --git a/entry.go b/entry.go index 225bdb6..eb4ae5c 100644 --- a/entry.go +++ b/entry.go @@ -168,6 +168,12 @@ func (entry *Entry) Debug(args ...interface{}) { } } +func (entry *Entry) Trace(args ...interface{}) { + if entry.Logger.IsLevelEnabled(TraceLevel) { + entry.log(TraceLevel, fmt.Sprint(args...)) + } +} + func (entry *Entry) Print(args ...interface{}) { entry.Info(args...) } @@ -216,6 +222,12 @@ func (entry *Entry) Debugf(format string, args ...interface{}) { } } +func (entry *Entry) Tracef(format string, args ...interface{}) { + if entry.Logger.IsLevelEnabled(TraceLevel) { + entry.Trace(fmt.Sprintf(format, args...)) + } +} + func (entry *Entry) Infof(format string, args ...interface{}) { if entry.Logger.IsLevelEnabled(InfoLevel) { entry.Info(fmt.Sprintf(format, args...)) @@ -257,6 +269,12 @@ func (entry *Entry) Panicf(format string, args ...interface{}) { // Entry Println family functions +func (entry *Entry) Traceln(args ...interface{}) { + if entry.Logger.IsLevelEnabled(TraceLevel) { + entry.Trace(entry.sprintlnn(args...)) + } +} + func (entry *Entry) Debugln(args ...interface{}) { if entry.Logger.IsLevelEnabled(DebugLevel) { entry.Debug(entry.sprintlnn(args...)) diff --git a/example_basic_test.go b/example_basic_test.go index 5f3849b..9ff5655 100644 --- a/example_basic_test.go +++ b/example_basic_test.go @@ -12,7 +12,7 @@ func Example_basic() { log.Formatter = new(logrus.TextFormatter) //default log.Formatter.(*logrus.TextFormatter).DisableColors = true // remove colors log.Formatter.(*logrus.TextFormatter).DisableTimestamp = true // remove timestamp from test output - log.Level = logrus.DebugLevel + log.Level = logrus.TraceLevel log.Out = os.Stdout // file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666) @@ -37,6 +37,11 @@ func Example_basic() { } }() + log.WithFields(logrus.Fields{ + "animal": "walrus", + "number": 0, + }).Trace("Went to the beach") + log.WithFields(logrus.Fields{ "animal": "walrus", "number": 8, @@ -62,6 +67,7 @@ func Example_basic() { }).Panic("It's over 9000!") // Output: + // level=trace msg="Went to the beach" animal=walrus number=0 // level=debug msg="Started observing beach" animal=walrus number=8 // level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10 // level=warning msg="The group's number increased tremendously!" number=122 omg=true diff --git a/exported.go b/exported.go index fb2a7a1..fb261aa 100644 --- a/exported.go +++ b/exported.go @@ -77,6 +77,11 @@ func WithTime(t time.Time) *Entry { return std.WithTime(t) } +// Trace logs a message at level Trace on the standard logger. +func Trace(args ...interface{}) { + std.Trace(args...) +} + // Debug logs a message at level Debug on the standard logger. func Debug(args ...interface{}) { std.Debug(args...) @@ -117,6 +122,11 @@ func Fatal(args ...interface{}) { std.Fatal(args...) } +// Tracef logs a message at level Debug on the standard logger. +func Tracef(format string, args ...interface{}) { + std.Tracef(format, args...) +} + // Debugf logs a message at level Debug on the standard logger. func Debugf(format string, args ...interface{}) { std.Debugf(format, args...) @@ -157,6 +167,11 @@ func Fatalf(format string, args ...interface{}) { std.Fatalf(format, args...) } +// Traceln logs a message at level Debug on the standard logger. +func Traceln(args ...interface{}) { + std.Traceln(args...) +} + // Debugln logs a message at level Debug on the standard logger. func Debugln(args ...interface{}) { std.Debugln(args...) diff --git a/hook_test.go b/hook_test.go index 80b93b8..7196e99 100644 --- a/hook_test.go +++ b/hook_test.go @@ -21,6 +21,7 @@ func (hook *TestHook) Fire(entry *Entry) error { func (hook *TestHook) Levels() []Level { return []Level{ + TraceLevel, DebugLevel, InfoLevel, WarnLevel, @@ -53,6 +54,7 @@ func (hook *ModifyHook) Fire(entry *Entry) error { func (hook *ModifyHook) Levels() []Level { return []Level{ + TraceLevel, DebugLevel, InfoLevel, WarnLevel, diff --git a/hooks/syslog/syslog.go b/hooks/syslog/syslog.go index 329ce0d..02b8df3 100644 --- a/hooks/syslog/syslog.go +++ b/hooks/syslog/syslog.go @@ -43,7 +43,7 @@ func (hook *SyslogHook) Fire(entry *logrus.Entry) error { return hook.Writer.Warning(line) case logrus.InfoLevel: return hook.Writer.Info(line) - case logrus.DebugLevel: + case logrus.DebugLevel, logrus.TraceLevel: return hook.Writer.Debug(line) default: return nil diff --git a/logger.go b/logger.go index 1c934ed..52f1761 100644 --- a/logger.go +++ b/logger.go @@ -126,6 +126,14 @@ func (logger *Logger) WithTime(t time.Time) *Entry { return entry.WithTime(t) } +func (logger *Logger) Tracef(format string, args ...interface{}) { + if logger.IsLevelEnabled(TraceLevel) { + entry := logger.newEntry() + entry.Tracef(format, args...) + logger.releaseEntry(entry) + } +} + func (logger *Logger) Debugf(format string, args ...interface{}) { if logger.IsLevelEnabled(DebugLevel) { entry := logger.newEntry() @@ -189,6 +197,14 @@ func (logger *Logger) Panicf(format string, args ...interface{}) { } } +func (logger *Logger) Trace(args ...interface{}) { + if logger.IsLevelEnabled(TraceLevel) { + entry := logger.newEntry() + entry.Trace(args...) + logger.releaseEntry(entry) + } +} + func (logger *Logger) Debug(args ...interface{}) { if logger.IsLevelEnabled(DebugLevel) { entry := logger.newEntry() @@ -252,6 +268,14 @@ func (logger *Logger) Panic(args ...interface{}) { } } +func (logger *Logger) Traceln(args ...interface{}) { + if logger.IsLevelEnabled(TraceLevel) { + entry := logger.newEntry() + entry.Traceln(args...) + logger.releaseEntry(entry) + } +} + func (logger *Logger) Debugln(args ...interface{}) { if logger.IsLevelEnabled(DebugLevel) { entry := logger.newEntry() diff --git a/logrus.go b/logrus.go index 6fff506..601d5e0 100644 --- a/logrus.go +++ b/logrus.go @@ -15,6 +15,8 @@ type Level uint32 // Convert the Level to a string. E.g. PanicLevel becomes "panic". func (level Level) String() string { switch level { + case TraceLevel: + return "trace" case DebugLevel: return "debug" case InfoLevel: @@ -47,6 +49,8 @@ func ParseLevel(lvl string) (Level, error) { return InfoLevel, nil case "debug": return DebugLevel, nil + case "trace": + return TraceLevel, nil } var l Level @@ -61,6 +65,7 @@ var AllLevels = []Level{ WarnLevel, InfoLevel, DebugLevel, + TraceLevel, } // These are the different logging levels. You can set the logging level to log @@ -82,6 +87,8 @@ const ( InfoLevel // DebugLevel level. Usually only enabled when debugging. Very verbose logging. DebugLevel + // TraceLevel level. Usually only enabled when debugging. Very verbose logging. Usually reserved for message traces + TraceLevel ) // Won't compile if StdLogger can't be realized by a log.Logger @@ -114,6 +121,7 @@ type FieldLogger interface { WithFields(fields Fields) *Entry WithError(err error) *Entry + Tracef(format string, args ...interface{}) Debugf(format string, args ...interface{}) Infof(format string, args ...interface{}) Printf(format string, args ...interface{}) @@ -123,6 +131,7 @@ type FieldLogger interface { Fatalf(format string, args ...interface{}) Panicf(format string, args ...interface{}) + Trace(args ...interface{}) Debug(args ...interface{}) Info(args ...interface{}) Print(args ...interface{}) @@ -132,6 +141,7 @@ type FieldLogger interface { Fatal(args ...interface{}) Panic(args ...interface{}) + Traceln(args ...interface{}) Debugln(args ...interface{}) Infoln(args ...interface{}) Println(args ...interface{}) diff --git a/text_formatter.go b/text_formatter.go index d4663b8..74dffcf 100644 --- a/text_formatter.go +++ b/text_formatter.go @@ -183,7 +183,7 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, timestampFormat string) { var levelColor int switch entry.Level { - case DebugLevel: + case DebugLevel, TraceLevel: levelColor = gray case WarnLevel: levelColor = yellow diff --git a/writer.go b/writer.go index 7bdebed..9e1f751 100644 --- a/writer.go +++ b/writer.go @@ -24,6 +24,8 @@ func (entry *Entry) WriterLevel(level Level) *io.PipeWriter { var printFunc func(args ...interface{}) switch level { + case TraceLevel: + printFunc = entry.Trace case DebugLevel: printFunc = entry.Debug case InfoLevel: From c7a33dc5de7efe87c53ee9598ab7b73a508f0be7 Mon Sep 17 00:00:00 2001 From: Giedrius Dubinskas Date: Mon, 2 Oct 2017 19:38:29 +0300 Subject: [PATCH 2/5] Add Trace level logging --- exported.go | 4 ++-- logrus.go | 3 ++- logrus_test.go | 9 +++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/exported.go b/exported.go index fb261aa..b9f1c9d 100644 --- a/exported.go +++ b/exported.go @@ -122,7 +122,7 @@ func Fatal(args ...interface{}) { std.Fatal(args...) } -// Tracef logs a message at level Debug on the standard logger. +// Tracef logs a message at level Trace on the standard logger. func Tracef(format string, args ...interface{}) { std.Tracef(format, args...) } @@ -167,7 +167,7 @@ func Fatalf(format string, args ...interface{}) { std.Fatalf(format, args...) } -// Traceln logs a message at level Debug on the standard logger. +// Traceln logs a message at level Trace on the standard logger. func Traceln(args ...interface{}) { std.Traceln(args...) } diff --git a/logrus.go b/logrus.go index 601d5e0..d657c41 100644 --- a/logrus.go +++ b/logrus.go @@ -87,7 +87,8 @@ const ( InfoLevel // DebugLevel level. Usually only enabled when debugging. Very verbose logging. DebugLevel - // TraceLevel level. Usually only enabled when debugging. Very verbose logging. Usually reserved for message traces + // TraceLevel level. Usually only enabled when debugging. Very verbose logging. + // Usually reserved for message traces. TraceLevel ) diff --git a/logrus_test.go b/logrus_test.go index 97d15d7..210feef 100644 --- a/logrus_test.go +++ b/logrus_test.go @@ -303,6 +303,7 @@ func TestDoubleLoggingDoesntPrefixPreviousFields(t *testing.T) { } func TestConvertLevelToString(t *testing.T) { + assert.Equal(t, "trace", TraceLevel.String()) assert.Equal(t, "debug", DebugLevel.String()) assert.Equal(t, "info", InfoLevel.String()) assert.Equal(t, "warning", WarnLevel.String()) @@ -368,6 +369,14 @@ func TestParseLevel(t *testing.T) { assert.Nil(t, err) assert.Equal(t, DebugLevel, l) + l, err = ParseLevel("trace") + assert.Nil(t, err) + assert.Equal(t, TraceLevel, l) + + l, err = ParseLevel("TRACE") + assert.Nil(t, err) + assert.Equal(t, TraceLevel, l) + l, err = ParseLevel("invalid") assert.Equal(t, "not a valid logrus Level: \"invalid\"", err.Error()) } From ef9d84e9b3d46ec3b1520d235295a78c586bdc11 Mon Sep 17 00:00:00 2001 From: Maxim Korolyov Date: Tue, 28 Aug 2018 18:13:29 +0300 Subject: [PATCH 3/5] Added trace log level. --- README.md | 3 ++- entry.go | 34 +++++++++++++++++----------------- logrus.go | 3 +-- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 072e99b..f088432 100644 --- a/README.md +++ b/README.md @@ -246,9 +246,10 @@ A list of currently known of service hook can be found in this wiki [page](https #### Level logging -Logrus has six logging levels: Debug, Info, Warning, Error, Fatal and Panic. +Logrus has seven logging levels: Trace, Debug, Info, Warning, Error, Fatal and Panic. ```go +log.Trace("Something very low level.") log.Debug("Useful debugging information.") log.Info("Something noteworthy happened!") log.Warn("You should probably take a look at this.") diff --git a/entry.go b/entry.go index eb4ae5c..a76be76 100644 --- a/entry.go +++ b/entry.go @@ -23,9 +23,9 @@ func init() { var ErrorKey = "error" // An entry is the final or intermediate Logrus logging entry. It contains all -// the fields passed with WithField{,s}. It's finally logged when Debug, Info, -// Warn, Error, Fatal or Panic is called on it. These objects can be reused and -// passed around as much as you wish to avoid field duplication. +// the fields passed with WithField{,s}. It's finally logged when Trace, Debug, +// Info, Warn, Error, Fatal or Panic is called on it. These objects can be +// reused and passed around as much as you wish to avoid field duplication. type Entry struct { Logger *Logger @@ -35,11 +35,11 @@ type Entry struct { // Time at which the log entry was created Time time.Time - // Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic + // Level the log entry was logged at: Trace, Debug, Info, Warn, Error, Fatal or Panic // This field will be set on entry firing and the value will be equal to the one in Logger struct field. Level Level - // Message passed to Debug, Info, Warn, Error, Fatal or Panic + // Message passed to Trace, Debug, Info, Warn, Error, Fatal or Panic Message string // When formatter is called in entry.log(), a Buffer may be set to entry @@ -162,18 +162,18 @@ func (entry *Entry) write() { } } -func (entry *Entry) Debug(args ...interface{}) { - if entry.Logger.IsLevelEnabled(DebugLevel) { - entry.log(DebugLevel, fmt.Sprint(args...)) - } -} - func (entry *Entry) Trace(args ...interface{}) { if entry.Logger.IsLevelEnabled(TraceLevel) { entry.log(TraceLevel, fmt.Sprint(args...)) } } +func (entry *Entry) Debug(args ...interface{}) { + if entry.Logger.IsLevelEnabled(DebugLevel) { + entry.log(DebugLevel, fmt.Sprint(args...)) + } +} + func (entry *Entry) Print(args ...interface{}) { entry.Info(args...) } @@ -216,18 +216,18 @@ func (entry *Entry) Panic(args ...interface{}) { // Entry Printf family functions -func (entry *Entry) Debugf(format string, args ...interface{}) { - if entry.Logger.IsLevelEnabled(DebugLevel) { - entry.Debug(fmt.Sprintf(format, args...)) - } -} - func (entry *Entry) Tracef(format string, args ...interface{}) { if entry.Logger.IsLevelEnabled(TraceLevel) { entry.Trace(fmt.Sprintf(format, args...)) } } +func (entry *Entry) Debugf(format string, args ...interface{}) { + if entry.Logger.IsLevelEnabled(DebugLevel) { + entry.Debug(fmt.Sprintf(format, args...)) + } +} + func (entry *Entry) Infof(format string, args ...interface{}) { if entry.Logger.IsLevelEnabled(InfoLevel) { entry.Info(fmt.Sprintf(format, args...)) diff --git a/logrus.go b/logrus.go index d657c41..8834b5b 100644 --- a/logrus.go +++ b/logrus.go @@ -87,8 +87,7 @@ const ( InfoLevel // DebugLevel level. Usually only enabled when debugging. Very verbose logging. DebugLevel - // TraceLevel level. Usually only enabled when debugging. Very verbose logging. - // Usually reserved for message traces. + // TraceLevel level. Designates finer-grained informational events than the Debug. TraceLevel ) From b54cafe5cee93a35bf6b061e261e8265ea0a628c Mon Sep 17 00:00:00 2001 From: Loren Osborn Date: Thu, 18 Oct 2018 09:33:43 -0700 Subject: [PATCH 4/5] Addresses @stevvooe's backward compatibility concerns. --- logrus.go | 12 +++++++++--- logrus_test.go | 7 +++++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/logrus.go b/logrus.go index 8834b5b..03046b6 100644 --- a/logrus.go +++ b/logrus.go @@ -121,7 +121,6 @@ type FieldLogger interface { WithFields(fields Fields) *Entry WithError(err error) *Entry - Tracef(format string, args ...interface{}) Debugf(format string, args ...interface{}) Infof(format string, args ...interface{}) Printf(format string, args ...interface{}) @@ -131,7 +130,6 @@ type FieldLogger interface { Fatalf(format string, args ...interface{}) Panicf(format string, args ...interface{}) - Trace(args ...interface{}) Debug(args ...interface{}) Info(args ...interface{}) Print(args ...interface{}) @@ -141,7 +139,6 @@ type FieldLogger interface { Fatal(args ...interface{}) Panic(args ...interface{}) - Traceln(args ...interface{}) Debugln(args ...interface{}) Infoln(args ...interface{}) Println(args ...interface{}) @@ -158,3 +155,12 @@ type FieldLogger interface { // IsFatalEnabled() bool // IsPanicEnabled() bool } + +// Ext1FieldLogger (the first extension to FieldLogger) is superfluous, it is +// here for consistancy. Do not use. Use Logger or Entry instead. +type Ext1FieldLogger interface { + FieldLogger + Tracef(format string, args ...interface{}) + Trace(args ...interface{}) + Traceln(args ...interface{}) +} diff --git a/logrus_test.go b/logrus_test.go index 210feef..748f0ba 100644 --- a/logrus_test.go +++ b/logrus_test.go @@ -453,9 +453,12 @@ func TestReplaceHooks(t *testing.T) { } // Compile test -func TestLogrusInterface(t *testing.T) { +func TestLogrusInterfaces(t *testing.T) { var buffer bytes.Buffer - fn := func(l FieldLogger) { + // This verifies FieldLogger and Ext1FieldLogger work as designed. + // Please don't use them. Use Logger and Entry directly. + fn := func(xl Ext1FieldLogger) { + var l FieldLogger = xl b := l.WithField("key", "value") b.Debug("Test") } From ed3ffa01907342213754448cb455dcc26d8e0a6d Mon Sep 17 00:00:00 2001 From: Loren Osborn Date: Thu, 18 Oct 2018 22:35:59 -0700 Subject: [PATCH 5/5] PR#844: Added Trace to TestLogLevelEnabled() (requested by @dgsb) --- logrus_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/logrus_test.go b/logrus_test.go index 748f0ba..ccdf5cc 100644 --- a/logrus_test.go +++ b/logrus_test.go @@ -506,6 +506,7 @@ func TestLogLevelEnabled(t *testing.T) { assert.Equal(t, false, log.IsLevelEnabled(WarnLevel)) assert.Equal(t, false, log.IsLevelEnabled(InfoLevel)) assert.Equal(t, false, log.IsLevelEnabled(DebugLevel)) + assert.Equal(t, false, log.IsLevelEnabled(TraceLevel)) log.SetLevel(FatalLevel) assert.Equal(t, true, log.IsLevelEnabled(PanicLevel)) @@ -514,6 +515,7 @@ func TestLogLevelEnabled(t *testing.T) { assert.Equal(t, false, log.IsLevelEnabled(WarnLevel)) assert.Equal(t, false, log.IsLevelEnabled(InfoLevel)) assert.Equal(t, false, log.IsLevelEnabled(DebugLevel)) + assert.Equal(t, false, log.IsLevelEnabled(TraceLevel)) log.SetLevel(ErrorLevel) assert.Equal(t, true, log.IsLevelEnabled(PanicLevel)) @@ -522,6 +524,7 @@ func TestLogLevelEnabled(t *testing.T) { assert.Equal(t, false, log.IsLevelEnabled(WarnLevel)) assert.Equal(t, false, log.IsLevelEnabled(InfoLevel)) assert.Equal(t, false, log.IsLevelEnabled(DebugLevel)) + assert.Equal(t, false, log.IsLevelEnabled(TraceLevel)) log.SetLevel(WarnLevel) assert.Equal(t, true, log.IsLevelEnabled(PanicLevel)) @@ -530,6 +533,7 @@ func TestLogLevelEnabled(t *testing.T) { assert.Equal(t, true, log.IsLevelEnabled(WarnLevel)) assert.Equal(t, false, log.IsLevelEnabled(InfoLevel)) assert.Equal(t, false, log.IsLevelEnabled(DebugLevel)) + assert.Equal(t, false, log.IsLevelEnabled(TraceLevel)) log.SetLevel(InfoLevel) assert.Equal(t, true, log.IsLevelEnabled(PanicLevel)) @@ -538,6 +542,7 @@ func TestLogLevelEnabled(t *testing.T) { assert.Equal(t, true, log.IsLevelEnabled(WarnLevel)) assert.Equal(t, true, log.IsLevelEnabled(InfoLevel)) assert.Equal(t, false, log.IsLevelEnabled(DebugLevel)) + assert.Equal(t, false, log.IsLevelEnabled(TraceLevel)) log.SetLevel(DebugLevel) assert.Equal(t, true, log.IsLevelEnabled(PanicLevel)) @@ -546,4 +551,14 @@ func TestLogLevelEnabled(t *testing.T) { assert.Equal(t, true, log.IsLevelEnabled(WarnLevel)) assert.Equal(t, true, log.IsLevelEnabled(InfoLevel)) assert.Equal(t, true, log.IsLevelEnabled(DebugLevel)) + assert.Equal(t, false, log.IsLevelEnabled(TraceLevel)) + + log.SetLevel(TraceLevel) + assert.Equal(t, true, log.IsLevelEnabled(PanicLevel)) + assert.Equal(t, true, log.IsLevelEnabled(FatalLevel)) + assert.Equal(t, true, log.IsLevelEnabled(ErrorLevel)) + assert.Equal(t, true, log.IsLevelEnabled(WarnLevel)) + assert.Equal(t, true, log.IsLevelEnabled(InfoLevel)) + assert.Equal(t, true, log.IsLevelEnabled(DebugLevel)) + assert.Equal(t, true, log.IsLevelEnabled(TraceLevel)) }