Add TraceLevel (#158)

This commit is contained in:
CrazyMax 2019-11-04 20:39:22 +01:00 committed by Olivier Poitrey
parent 43d05e8ddf
commit 4502cc1942
15 changed files with 101 additions and 20 deletions

View File

@ -125,6 +125,7 @@ func main() {
* warn (`zerolog.WarnLevel`, 2) * warn (`zerolog.WarnLevel`, 2)
* info (`zerolog.InfoLevel`, 1) * info (`zerolog.InfoLevel`, 1)
* debug (`zerolog.DebugLevel`, 0) * debug (`zerolog.DebugLevel`, 0)
* trace (`zerolog.TraceLevel`, -1)
You can set the Global logging level to any of these options using the `SetGlobalLevel` function in the zerolog package, passing in one of the given constants above, e.g. `zerolog.InfoLevel` would be the "info" level. Whichever level is chosen, all logs with a level greater than or equal to that level will be written. To turn off logging entirely, pass the `zerolog.Disabled` constant. You can set the Global logging level to any of these options using the `SetGlobalLevel` function in the zerolog package, passing in one of the given constants above, e.g. `zerolog.InfoLevel` would be the "info" level. Whichever level is chosen, all logs with a level greater than or equal to that level will be written. To turn off logging entirely, pass the `zerolog.Disabled` constant.

View File

@ -108,6 +108,19 @@ func ExampleLogger_Printf() {
// Output: {"level":"debug","message":"hello world"} // Output: {"level":"debug","message":"hello world"}
} }
func ExampleLogger_Trace() {
dst := bytes.Buffer{}
log := New(&dst)
log.Trace().
Str("foo", "bar").
Int("n", 123).
Msg("hello world")
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
// Output: {"level":"trace","foo":"bar","n":123,"message":"hello world"}
}
func ExampleLogger_Debug() { func ExampleLogger_Debug() {
dst := bytes.Buffer{} dst := bytes.Buffer{}
log := New(&dst) log := New(&dst)

View File

@ -317,6 +317,8 @@ func consoleDefaultFormatLevel(noColor bool) Formatter {
var l string var l string
if ll, ok := i.(string); ok { if ll, ok := i.(string); ok {
switch ll { switch ll {
case "trace":
l = colorize("TRC", colorMagenta, noColor)
case "debug": case "debug":
l = colorize("DBG", colorYellow, noColor) l = colorize("DBG", colorYellow, noColor)
case "info": case "info":

1
ctx.go
View File

@ -7,6 +7,7 @@ import (
var disabledLogger *Logger var disabledLogger *Logger
func init() { func init() {
SetGlobalLevel(TraceLevel)
l := Nop() l := Nop()
disabledLogger = &l disabledLogger = &l
} }

View File

@ -2,9 +2,9 @@ package zerolog
import ( import (
"strconv" "strconv"
"sync/atomic"
"time" "time"
) )
import "sync/atomic"
const ( const (
// TimeFormatUnix defines a time format that makes time fields to be // TimeFormatUnix defines a time format that makes time fields to be
@ -83,8 +83,8 @@ var (
) )
var ( var (
gLevel = new(uint32) gLevel = new(int32)
disableSampling = new(uint32) disableSampling = new(int32)
) )
// SetGlobalLevel sets the global override for log level. If this // SetGlobalLevel sets the global override for log level. If this
@ -92,23 +92,23 @@ var (
// //
// To globally disable logs, set GlobalLevel to Disabled. // To globally disable logs, set GlobalLevel to Disabled.
func SetGlobalLevel(l Level) { func SetGlobalLevel(l Level) {
atomic.StoreUint32(gLevel, uint32(l)) atomic.StoreInt32(gLevel, int32(l))
} }
// GlobalLevel returns the current global log level // GlobalLevel returns the current global log level
func GlobalLevel() Level { func GlobalLevel() Level {
return Level(atomic.LoadUint32(gLevel)) return Level(atomic.LoadInt32(gLevel))
} }
// DisableSampling will disable sampling in all Loggers if true. // DisableSampling will disable sampling in all Loggers if true.
func DisableSampling(v bool) { func DisableSampling(v bool) {
var i uint32 var i int32
if v { if v {
i = 1 i = 1
} }
atomic.StoreUint32(disableSampling, i) atomic.StoreInt32(disableSampling, i)
} }
func samplingDisabled() bool { func samplingDisabled() bool {
return atomic.LoadUint32(disableSampling) == 1 return atomic.LoadInt32(disableSampling) == 1
} }

View File

@ -17,12 +17,16 @@ func (h HookFunc) Run(e *Event, level Level, message string) {
// LevelHook applies a different hook for each level. // LevelHook applies a different hook for each level.
type LevelHook struct { type LevelHook struct {
NoLevelHook, DebugHook, InfoHook, WarnHook, ErrorHook, FatalHook, PanicHook Hook NoLevelHook, TraceHook, DebugHook, InfoHook, WarnHook, ErrorHook, FatalHook, PanicHook Hook
} }
// Run implements the Hook interface. // Run implements the Hook interface.
func (h LevelHook) Run(e *Event, level Level, message string) { func (h LevelHook) Run(e *Event, level Level, message string) {
switch level { switch level {
case TraceLevel:
if h.TraceHook != nil {
h.TraceHook.Run(e, level, message)
}
case DebugLevel: case DebugLevel:
if h.DebugHook != nil { if h.DebugHook != nil {
h.DebugHook.Run(e, level, message) h.DebugHook.Run(e, level, message)

View File

@ -48,6 +48,8 @@ func levelToJPrio(zLevel string) journal.Priority {
lvl, _ := zerolog.ParseLevel(zLevel) lvl, _ := zerolog.ParseLevel(zLevel)
switch lvl { switch lvl {
case zerolog.TraceLevel:
return journal.PriDebug
case zerolog.DebugLevel: case zerolog.DebugLevel:
return journal.PriDebug return journal.PriDebug
case zerolog.InfoLevel: case zerolog.InfoLevel:

19
log.go
View File

@ -107,9 +107,11 @@ import (
) )
// Level defines log levels. // Level defines log levels.
type Level uint8 type Level int8
const ( const (
// TraceLevel defines trace log level.
TraceLevel Level = -1
// DebugLevel defines debug log level. // DebugLevel defines debug log level.
DebugLevel Level = iota DebugLevel Level = iota
// InfoLevel defines info log level. // InfoLevel defines info log level.
@ -130,6 +132,8 @@ const (
func (l Level) String() string { func (l Level) String() string {
switch l { switch l {
case TraceLevel:
return "trace"
case DebugLevel: case DebugLevel:
return "debug" return "debug"
case InfoLevel: case InfoLevel:
@ -152,6 +156,8 @@ func (l Level) String() string {
// returns an error if the input string does not match known values. // returns an error if the input string does not match known values.
func ParseLevel(levelStr string) (Level, error) { func ParseLevel(levelStr string) (Level, error) {
switch levelStr { switch levelStr {
case LevelFieldMarshalFunc(TraceLevel):
return TraceLevel, nil
case LevelFieldMarshalFunc(DebugLevel): case LevelFieldMarshalFunc(DebugLevel):
return DebugLevel, nil return DebugLevel, nil
case LevelFieldMarshalFunc(InfoLevel): case LevelFieldMarshalFunc(InfoLevel):
@ -198,7 +204,7 @@ func New(w io.Writer) Logger {
if !ok { if !ok {
lw = levelWriterAdapter{w} lw = levelWriterAdapter{w}
} }
return Logger{w: lw} return Logger{w: lw, level: TraceLevel}
} }
// Nop returns a disabled logger for which all operation are no-op. // Nop returns a disabled logger for which all operation are no-op.
@ -268,6 +274,13 @@ func (l Logger) Hook(h Hook) Logger {
return l return l
} }
// Trace starts a new message with trace level.
//
// You must call Msg on the returned event in order to send the event.
func (l *Logger) Trace() *Event {
return l.newEvent(TraceLevel, nil)
}
// Debug starts a new message with debug level. // Debug starts a new message with debug level.
// //
// You must call Msg on the returned event in order to send the event. // You must call Msg on the returned event in order to send the event.
@ -331,6 +344,8 @@ func (l *Logger) Panic() *Event {
// You must call Msg on the returned event in order to send the event. // You must call Msg on the returned event in order to send the event.
func (l *Logger) WithLevel(level Level) *Event { func (l *Logger) WithLevel(level Level) *Event {
switch level { switch level {
case TraceLevel:
return l.Trace()
case DebugLevel: case DebugLevel:
return l.Debug() return l.Debug()
case InfoLevel: case InfoLevel:

View File

@ -37,6 +37,13 @@ func Hook(h zerolog.Hook) zerolog.Logger {
return Logger.Hook(h) return Logger.Hook(h)
} }
// Trace starts a new message with trace level.
//
// You must call Msg on the returned event in order to send the event.
func Trace() *zerolog.Event {
return Logger.Trace()
}
// Debug starts a new message with debug level. // Debug starts a new message with debug level.
// //
// You must call Msg on the returned event in order to send the event. // You must call Msg on the returned event in order to send the event.

View File

@ -54,6 +54,14 @@ func ExampleLog() {
// Output: {"time":1199811905,"message":"hello world"} // Output: {"time":1199811905,"message":"hello world"}
} }
// Example of a log at a particular "level" (in this case, "trace")
func ExampleTrace() {
setup()
log.Trace().Msg("hello world")
// Output: {"level":"trace","time":1199811905,"message":"hello world"}
}
// Example of a log at a particular "level" (in this case, "debug") // Example of a log at a particular "level" (in this case, "debug")
func ExampleDebug() { func ExampleDebug() {
setup() setup()

View File

@ -95,6 +95,17 @@ func ExampleLogger_Printf() {
// Output: {"level":"debug","message":"hello world"} // Output: {"level":"debug","message":"hello world"}
} }
func ExampleLogger_Trace() {
log := zerolog.New(os.Stdout)
log.Trace().
Str("foo", "bar").
Int("n", 123).
Msg("hello world")
// Output: {"level":"trace","foo":"bar","n":123,"message":"hello world"}
}
func ExampleLogger_Debug() { func ExampleLogger_Debug() {
log := zerolog.New(os.Stdout) log := zerolog.New(os.Stdout)

View File

@ -526,30 +526,34 @@ func TestLevelWriter(t *testing.T) {
}{}, }{},
} }
log := New(lw) log := New(lw)
log.Trace().Msg("0")
log.Debug().Msg("1") log.Debug().Msg("1")
log.Info().Msg("2") log.Info().Msg("2")
log.Warn().Msg("3") log.Warn().Msg("3")
log.Error().Msg("4") log.Error().Msg("4")
log.Log().Msg("nolevel-1") log.Log().Msg("nolevel-1")
log.WithLevel(DebugLevel).Msg("5") log.WithLevel(TraceLevel).Msg("5")
log.WithLevel(InfoLevel).Msg("6") log.WithLevel(DebugLevel).Msg("6")
log.WithLevel(WarnLevel).Msg("7") log.WithLevel(InfoLevel).Msg("7")
log.WithLevel(ErrorLevel).Msg("8") log.WithLevel(WarnLevel).Msg("8")
log.WithLevel(ErrorLevel).Msg("9")
log.WithLevel(NoLevel).Msg("nolevel-2") log.WithLevel(NoLevel).Msg("nolevel-2")
want := []struct { want := []struct {
l Level l Level
p string p string
}{ }{
{TraceLevel, `{"level":"trace","message":"0"}` + "\n"},
{DebugLevel, `{"level":"debug","message":"1"}` + "\n"}, {DebugLevel, `{"level":"debug","message":"1"}` + "\n"},
{InfoLevel, `{"level":"info","message":"2"}` + "\n"}, {InfoLevel, `{"level":"info","message":"2"}` + "\n"},
{WarnLevel, `{"level":"warn","message":"3"}` + "\n"}, {WarnLevel, `{"level":"warn","message":"3"}` + "\n"},
{ErrorLevel, `{"level":"error","message":"4"}` + "\n"}, {ErrorLevel, `{"level":"error","message":"4"}` + "\n"},
{NoLevel, `{"message":"nolevel-1"}` + "\n"}, {NoLevel, `{"message":"nolevel-1"}` + "\n"},
{DebugLevel, `{"level":"debug","message":"5"}` + "\n"}, {TraceLevel, `{"level":"trace","message":"5"}` + "\n"},
{InfoLevel, `{"level":"info","message":"6"}` + "\n"}, {DebugLevel, `{"level":"debug","message":"6"}` + "\n"},
{WarnLevel, `{"level":"warn","message":"7"}` + "\n"}, {InfoLevel, `{"level":"info","message":"7"}` + "\n"},
{ErrorLevel, `{"level":"error","message":"8"}` + "\n"}, {WarnLevel, `{"level":"warn","message":"8"}` + "\n"},
{ErrorLevel, `{"level":"error","message":"9"}` + "\n"},
{NoLevel, `{"message":"nolevel-2"}` + "\n"}, {NoLevel, `{"message":"nolevel-2"}` + "\n"},
} }
if got := lw.ops; !reflect.DeepEqual(got, want) { if got := lw.ops; !reflect.DeepEqual(got, want) {

View File

@ -104,11 +104,15 @@ func (s *BurstSampler) inc() uint32 {
// LevelSampler applies a different sampler for each level. // LevelSampler applies a different sampler for each level.
type LevelSampler struct { type LevelSampler struct {
DebugSampler, InfoSampler, WarnSampler, ErrorSampler Sampler TraceSampler, DebugSampler, InfoSampler, WarnSampler, ErrorSampler Sampler
} }
func (s LevelSampler) Sample(lvl Level) bool { func (s LevelSampler) Sample(lvl Level) bool {
switch lvl { switch lvl {
case TraceLevel:
if s.TraceSampler != nil {
return s.TraceSampler.Sample(lvl)
}
case DebugLevel: case DebugLevel:
if s.DebugSampler != nil { if s.DebugSampler != nil {
return s.DebugSampler.Sample(lvl) return s.DebugSampler.Sample(lvl)

View File

@ -10,6 +10,7 @@ import (
// SyslogWriter is an interface matching a syslog.Writer struct. // SyslogWriter is an interface matching a syslog.Writer struct.
type SyslogWriter interface { type SyslogWriter interface {
io.Writer io.Writer
Trace(m string) error
Debug(m string) error Debug(m string) error
Info(m string) error Info(m string) error
Warning(m string) error Warning(m string) error
@ -35,6 +36,8 @@ func (sw syslogWriter) Write(p []byte) (n int, err error) {
// WriteLevel implements LevelWriter interface. // WriteLevel implements LevelWriter interface.
func (sw syslogWriter) WriteLevel(level Level, p []byte) (n int, err error) { func (sw syslogWriter) WriteLevel(level Level, p []byte) (n int, err error) {
switch level { switch level {
case TraceLevel:
err = sw.w.Trace(string(p))
case DebugLevel: case DebugLevel:
err = sw.w.Debug(string(p)) err = sw.w.Debug(string(p))
case InfoLevel: case InfoLevel:

View File

@ -17,6 +17,10 @@ type syslogTestWriter struct {
func (w *syslogTestWriter) Write(p []byte) (int, error) { func (w *syslogTestWriter) Write(p []byte) (int, error) {
return 0, nil return 0, nil
} }
func (w *syslogTestWriter) Trace(m string) error {
w.events = append(w.events, syslogEvent{"Trace", m})
return nil
}
func (w *syslogTestWriter) Debug(m string) error { func (w *syslogTestWriter) Debug(m string) error {
w.events = append(w.events, syslogEvent{"Debug", m}) w.events = append(w.events, syslogEvent{"Debug", m})
return nil return nil
@ -45,12 +49,14 @@ func (w *syslogTestWriter) Crit(m string) error {
func TestSyslogWriter(t *testing.T) { func TestSyslogWriter(t *testing.T) {
sw := &syslogTestWriter{} sw := &syslogTestWriter{}
log := New(SyslogLevelWriter(sw)) log := New(SyslogLevelWriter(sw))
log.Trace().Msg("trace")
log.Debug().Msg("debug") log.Debug().Msg("debug")
log.Info().Msg("info") log.Info().Msg("info")
log.Warn().Msg("warn") log.Warn().Msg("warn")
log.Error().Msg("error") log.Error().Msg("error")
log.Log().Msg("nolevel") log.Log().Msg("nolevel")
want := []syslogEvent{ want := []syslogEvent{
{"Trace", `{"level":"trace","message":"trace"}` + "\n"},
{"Debug", `{"level":"debug","message":"debug"}` + "\n"}, {"Debug", `{"level":"debug","message":"debug"}` + "\n"},
{"Info", `{"level":"info","message":"info"}` + "\n"}, {"Info", `{"level":"info","message":"info"}` + "\n"},
{"Warning", `{"level":"warn","message":"warn"}` + "\n"}, {"Warning", `{"level":"warn","message":"warn"}` + "\n"},