Merge pull request #844 from loren-osborn/pull/652_AddTraceLevelLogging

Added TRACE level logging.
This commit is contained in:
David Bariod 2018-10-20 07:09:04 +02:00 committed by GitHub
commit 08e90462da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 123 additions and 11 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
logrus logrus
vendor

View File

@ -246,9 +246,10 @@ A list of currently known of service hook can be found in this wiki [page](https
#### Level logging #### 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 ```go
log.Trace("Something very low level.")
log.Debug("Useful debugging information.") log.Debug("Useful debugging information.")
log.Info("Something noteworthy happened!") log.Info("Something noteworthy happened!")
log.Warn("You should probably take a look at this.") log.Warn("You should probably take a look at this.")

View File

@ -23,9 +23,9 @@ func init() {
var ErrorKey = "error" var ErrorKey = "error"
// An entry is the final or intermediate Logrus logging entry. It contains all // 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, // the fields passed with WithField{,s}. It's finally logged when Trace, Debug,
// Warn, Error, Fatal or Panic is called on it. These objects can be reused and // Info, Warn, Error, Fatal or Panic is called on it. These objects can be
// passed around as much as you wish to avoid field duplication. // reused and passed around as much as you wish to avoid field duplication.
type Entry struct { type Entry struct {
Logger *Logger Logger *Logger
@ -35,11 +35,11 @@ type Entry struct {
// Time at which the log entry was created // Time at which the log entry was created
Time time.Time 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. // This field will be set on entry firing and the value will be equal to the one in Logger struct field.
Level Level 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 Message string
// When formatter is called in entry.log(), a Buffer may be set to entry // When formatter is called in entry.log(), a Buffer may be set to entry
@ -162,6 +162,12 @@ func (entry *Entry) write() {
} }
} }
func (entry *Entry) Trace(args ...interface{}) {
if entry.Logger.IsLevelEnabled(TraceLevel) {
entry.log(TraceLevel, fmt.Sprint(args...))
}
}
func (entry *Entry) Debug(args ...interface{}) { func (entry *Entry) Debug(args ...interface{}) {
if entry.Logger.IsLevelEnabled(DebugLevel) { if entry.Logger.IsLevelEnabled(DebugLevel) {
entry.log(DebugLevel, fmt.Sprint(args...)) entry.log(DebugLevel, fmt.Sprint(args...))
@ -210,6 +216,12 @@ func (entry *Entry) Panic(args ...interface{}) {
// Entry Printf family functions // Entry Printf family functions
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{}) { func (entry *Entry) Debugf(format string, args ...interface{}) {
if entry.Logger.IsLevelEnabled(DebugLevel) { if entry.Logger.IsLevelEnabled(DebugLevel) {
entry.Debug(fmt.Sprintf(format, args...)) entry.Debug(fmt.Sprintf(format, args...))
@ -257,6 +269,12 @@ func (entry *Entry) Panicf(format string, args ...interface{}) {
// Entry Println family functions // 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{}) { func (entry *Entry) Debugln(args ...interface{}) {
if entry.Logger.IsLevelEnabled(DebugLevel) { if entry.Logger.IsLevelEnabled(DebugLevel) {
entry.Debug(entry.sprintlnn(args...)) entry.Debug(entry.sprintlnn(args...))

View File

@ -12,7 +12,7 @@ func Example_basic() {
log.Formatter = new(logrus.TextFormatter) //default log.Formatter = new(logrus.TextFormatter) //default
log.Formatter.(*logrus.TextFormatter).DisableColors = true // remove colors log.Formatter.(*logrus.TextFormatter).DisableColors = true // remove colors
log.Formatter.(*logrus.TextFormatter).DisableTimestamp = true // remove timestamp from test output log.Formatter.(*logrus.TextFormatter).DisableTimestamp = true // remove timestamp from test output
log.Level = logrus.DebugLevel log.Level = logrus.TraceLevel
log.Out = os.Stdout log.Out = os.Stdout
// file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666) // 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{ log.WithFields(logrus.Fields{
"animal": "walrus", "animal": "walrus",
"number": 8, "number": 8,
@ -62,6 +67,7 @@ func Example_basic() {
}).Panic("It's over 9000!") }).Panic("It's over 9000!")
// Output: // Output:
// level=trace msg="Went to the beach" animal=walrus number=0
// level=debug msg="Started observing beach" animal=walrus number=8 // 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=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 // level=warning msg="The group's number increased tremendously!" number=122 omg=true

View File

@ -77,6 +77,11 @@ func WithTime(t time.Time) *Entry {
return std.WithTime(t) 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. // Debug logs a message at level Debug on the standard logger.
func Debug(args ...interface{}) { func Debug(args ...interface{}) {
std.Debug(args...) std.Debug(args...)
@ -117,6 +122,11 @@ func Fatal(args ...interface{}) {
std.Fatal(args...) std.Fatal(args...)
} }
// Tracef logs a message at level Trace 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. // Debugf logs a message at level Debug on the standard logger.
func Debugf(format string, args ...interface{}) { func Debugf(format string, args ...interface{}) {
std.Debugf(format, args...) std.Debugf(format, args...)
@ -157,6 +167,11 @@ func Fatalf(format string, args ...interface{}) {
std.Fatalf(format, args...) std.Fatalf(format, args...)
} }
// Traceln logs a message at level Trace on the standard logger.
func Traceln(args ...interface{}) {
std.Traceln(args...)
}
// Debugln logs a message at level Debug on the standard logger. // Debugln logs a message at level Debug on the standard logger.
func Debugln(args ...interface{}) { func Debugln(args ...interface{}) {
std.Debugln(args...) std.Debugln(args...)

View File

@ -21,6 +21,7 @@ func (hook *TestHook) Fire(entry *Entry) error {
func (hook *TestHook) Levels() []Level { func (hook *TestHook) Levels() []Level {
return []Level{ return []Level{
TraceLevel,
DebugLevel, DebugLevel,
InfoLevel, InfoLevel,
WarnLevel, WarnLevel,
@ -53,6 +54,7 @@ func (hook *ModifyHook) Fire(entry *Entry) error {
func (hook *ModifyHook) Levels() []Level { func (hook *ModifyHook) Levels() []Level {
return []Level{ return []Level{
TraceLevel,
DebugLevel, DebugLevel,
InfoLevel, InfoLevel,
WarnLevel, WarnLevel,

View File

@ -43,7 +43,7 @@ func (hook *SyslogHook) Fire(entry *logrus.Entry) error {
return hook.Writer.Warning(line) return hook.Writer.Warning(line)
case logrus.InfoLevel: case logrus.InfoLevel:
return hook.Writer.Info(line) return hook.Writer.Info(line)
case logrus.DebugLevel: case logrus.DebugLevel, logrus.TraceLevel:
return hook.Writer.Debug(line) return hook.Writer.Debug(line)
default: default:
return nil return nil

View File

@ -126,6 +126,14 @@ func (logger *Logger) WithTime(t time.Time) *Entry {
return entry.WithTime(t) 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{}) { func (logger *Logger) Debugf(format string, args ...interface{}) {
if logger.IsLevelEnabled(DebugLevel) { if logger.IsLevelEnabled(DebugLevel) {
entry := logger.newEntry() 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{}) { func (logger *Logger) Debug(args ...interface{}) {
if logger.IsLevelEnabled(DebugLevel) { if logger.IsLevelEnabled(DebugLevel) {
entry := logger.newEntry() 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{}) { func (logger *Logger) Debugln(args ...interface{}) {
if logger.IsLevelEnabled(DebugLevel) { if logger.IsLevelEnabled(DebugLevel) {
entry := logger.newEntry() entry := logger.newEntry()

View File

@ -15,6 +15,8 @@ type Level uint32
// Convert the Level to a string. E.g. PanicLevel becomes "panic". // Convert the Level to a string. E.g. PanicLevel becomes "panic".
func (level Level) String() string { func (level Level) String() string {
switch level { switch level {
case TraceLevel:
return "trace"
case DebugLevel: case DebugLevel:
return "debug" return "debug"
case InfoLevel: case InfoLevel:
@ -47,6 +49,8 @@ func ParseLevel(lvl string) (Level, error) {
return InfoLevel, nil return InfoLevel, nil
case "debug": case "debug":
return DebugLevel, nil return DebugLevel, nil
case "trace":
return TraceLevel, nil
} }
var l Level var l Level
@ -61,6 +65,7 @@ var AllLevels = []Level{
WarnLevel, WarnLevel,
InfoLevel, InfoLevel,
DebugLevel, DebugLevel,
TraceLevel,
} }
// These are the different logging levels. You can set the logging level to log // These are the different logging levels. You can set the logging level to log
@ -82,6 +87,8 @@ const (
InfoLevel InfoLevel
// DebugLevel level. Usually only enabled when debugging. Very verbose logging. // DebugLevel level. Usually only enabled when debugging. Very verbose logging.
DebugLevel DebugLevel
// TraceLevel level. Designates finer-grained informational events than the Debug.
TraceLevel
) )
// Won't compile if StdLogger can't be realized by a log.Logger // Won't compile if StdLogger can't be realized by a log.Logger
@ -148,3 +155,12 @@ type FieldLogger interface {
// IsFatalEnabled() bool // IsFatalEnabled() bool
// IsPanicEnabled() 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{})
}

View File

@ -303,6 +303,7 @@ func TestDoubleLoggingDoesntPrefixPreviousFields(t *testing.T) {
} }
func TestConvertLevelToString(t *testing.T) { func TestConvertLevelToString(t *testing.T) {
assert.Equal(t, "trace", TraceLevel.String())
assert.Equal(t, "debug", DebugLevel.String()) assert.Equal(t, "debug", DebugLevel.String())
assert.Equal(t, "info", InfoLevel.String()) assert.Equal(t, "info", InfoLevel.String())
assert.Equal(t, "warning", WarnLevel.String()) assert.Equal(t, "warning", WarnLevel.String())
@ -368,6 +369,14 @@ func TestParseLevel(t *testing.T) {
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, DebugLevel, l) 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") l, err = ParseLevel("invalid")
assert.Equal(t, "not a valid logrus Level: \"invalid\"", err.Error()) assert.Equal(t, "not a valid logrus Level: \"invalid\"", err.Error())
} }
@ -444,9 +453,12 @@ func TestReplaceHooks(t *testing.T) {
} }
// Compile test // Compile test
func TestLogrusInterface(t *testing.T) { func TestLogrusInterfaces(t *testing.T) {
var buffer bytes.Buffer 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 := l.WithField("key", "value")
b.Debug("Test") b.Debug("Test")
} }
@ -494,6 +506,7 @@ func TestLogLevelEnabled(t *testing.T) {
assert.Equal(t, false, log.IsLevelEnabled(WarnLevel)) assert.Equal(t, false, log.IsLevelEnabled(WarnLevel))
assert.Equal(t, false, log.IsLevelEnabled(InfoLevel)) assert.Equal(t, false, log.IsLevelEnabled(InfoLevel))
assert.Equal(t, false, log.IsLevelEnabled(DebugLevel)) assert.Equal(t, false, log.IsLevelEnabled(DebugLevel))
assert.Equal(t, false, log.IsLevelEnabled(TraceLevel))
log.SetLevel(FatalLevel) log.SetLevel(FatalLevel)
assert.Equal(t, true, log.IsLevelEnabled(PanicLevel)) assert.Equal(t, true, log.IsLevelEnabled(PanicLevel))
@ -502,6 +515,7 @@ func TestLogLevelEnabled(t *testing.T) {
assert.Equal(t, false, log.IsLevelEnabled(WarnLevel)) assert.Equal(t, false, log.IsLevelEnabled(WarnLevel))
assert.Equal(t, false, log.IsLevelEnabled(InfoLevel)) assert.Equal(t, false, log.IsLevelEnabled(InfoLevel))
assert.Equal(t, false, log.IsLevelEnabled(DebugLevel)) assert.Equal(t, false, log.IsLevelEnabled(DebugLevel))
assert.Equal(t, false, log.IsLevelEnabled(TraceLevel))
log.SetLevel(ErrorLevel) log.SetLevel(ErrorLevel)
assert.Equal(t, true, log.IsLevelEnabled(PanicLevel)) assert.Equal(t, true, log.IsLevelEnabled(PanicLevel))
@ -510,6 +524,7 @@ func TestLogLevelEnabled(t *testing.T) {
assert.Equal(t, false, log.IsLevelEnabled(WarnLevel)) assert.Equal(t, false, log.IsLevelEnabled(WarnLevel))
assert.Equal(t, false, log.IsLevelEnabled(InfoLevel)) assert.Equal(t, false, log.IsLevelEnabled(InfoLevel))
assert.Equal(t, false, log.IsLevelEnabled(DebugLevel)) assert.Equal(t, false, log.IsLevelEnabled(DebugLevel))
assert.Equal(t, false, log.IsLevelEnabled(TraceLevel))
log.SetLevel(WarnLevel) log.SetLevel(WarnLevel)
assert.Equal(t, true, log.IsLevelEnabled(PanicLevel)) assert.Equal(t, true, log.IsLevelEnabled(PanicLevel))
@ -518,6 +533,7 @@ func TestLogLevelEnabled(t *testing.T) {
assert.Equal(t, true, log.IsLevelEnabled(WarnLevel)) assert.Equal(t, true, log.IsLevelEnabled(WarnLevel))
assert.Equal(t, false, log.IsLevelEnabled(InfoLevel)) assert.Equal(t, false, log.IsLevelEnabled(InfoLevel))
assert.Equal(t, false, log.IsLevelEnabled(DebugLevel)) assert.Equal(t, false, log.IsLevelEnabled(DebugLevel))
assert.Equal(t, false, log.IsLevelEnabled(TraceLevel))
log.SetLevel(InfoLevel) log.SetLevel(InfoLevel)
assert.Equal(t, true, log.IsLevelEnabled(PanicLevel)) assert.Equal(t, true, log.IsLevelEnabled(PanicLevel))
@ -526,6 +542,7 @@ func TestLogLevelEnabled(t *testing.T) {
assert.Equal(t, true, log.IsLevelEnabled(WarnLevel)) assert.Equal(t, true, log.IsLevelEnabled(WarnLevel))
assert.Equal(t, true, log.IsLevelEnabled(InfoLevel)) assert.Equal(t, true, log.IsLevelEnabled(InfoLevel))
assert.Equal(t, false, log.IsLevelEnabled(DebugLevel)) assert.Equal(t, false, log.IsLevelEnabled(DebugLevel))
assert.Equal(t, false, log.IsLevelEnabled(TraceLevel))
log.SetLevel(DebugLevel) log.SetLevel(DebugLevel)
assert.Equal(t, true, log.IsLevelEnabled(PanicLevel)) assert.Equal(t, true, log.IsLevelEnabled(PanicLevel))
@ -534,4 +551,14 @@ func TestLogLevelEnabled(t *testing.T) {
assert.Equal(t, true, log.IsLevelEnabled(WarnLevel)) assert.Equal(t, true, log.IsLevelEnabled(WarnLevel))
assert.Equal(t, true, log.IsLevelEnabled(InfoLevel)) assert.Equal(t, true, log.IsLevelEnabled(InfoLevel))
assert.Equal(t, true, log.IsLevelEnabled(DebugLevel)) 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))
} }

View File

@ -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) { func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, timestampFormat string) {
var levelColor int var levelColor int
switch entry.Level { switch entry.Level {
case DebugLevel: case DebugLevel, TraceLevel:
levelColor = gray levelColor = gray
case WarnLevel: case WarnLevel:
levelColor = yellow levelColor = yellow

View File

@ -24,6 +24,8 @@ func (entry *Entry) WriterLevel(level Level) *io.PipeWriter {
var printFunc func(args ...interface{}) var printFunc func(args ...interface{})
switch level { switch level {
case TraceLevel:
printFunc = entry.Trace
case DebugLevel: case DebugLevel:
printFunc = entry.Debug printFunc = entry.Debug
case InfoLevel: case InfoLevel: