Make GlobalLevel and DisableSampling thread safe

This commit is contained in:
Olivier Poitrey 2017-05-15 11:16:13 -07:00
parent 7f302b00ec
commit d0a1bd7e3e
4 changed files with 61 additions and 38 deletions

View File

@ -85,7 +85,7 @@ sublogger.Info().Msg("hello world")
### Level logging ### Level logging
```go ```go
zerolog.GlobalLevel = zerolog.InfoLevel zerolog.SetGlobalLevel(zerolog.InfoLevel)
log.Debug().Msg("filtered out message") log.Debug().Msg("filtered out message")
log.Info().Msg("routed message") log.Info().Msg("routed message")
@ -138,8 +138,8 @@ sampled.Info().Msg("will be logged every 10 messages")
Some settings can be changed and will by applied to all loggers: Some settings can be changed and will by applied to all loggers:
* `log.Logger`: You can set this value to customize the global logger (the one used by package level methods). * `log.Logger`: You can set this value to customize the global logger (the one used by package level methods).
* `zerolog.GlobalLevel`: Can raise the mimimum level of all loggers. Set this to `zerolog.Disable` to disable logging altogether (quiet mode). * `zerolog.SetGlobalLevel`: Can raise the mimimum level of all loggers. Set this to `zerolog.Disable` to disable logging altogether (quiet mode).
* `zerolog.SamplingDisable`: If set to `true`, all sampled loggers will stop sampling and issue 100% of their log events. * `zerolog.DisableSampling`: If argument is `true`, all sampled loggers will stop sampling and issue 100% of their log events.
* `zerolog.TimestampFieldName`: Can be set to customize `Timestamp` field name. * `zerolog.TimestampFieldName`: Can be set to customize `Timestamp` field name.
* `zerolog.LevelFieldName`: Can be set to customize level field name. * `zerolog.LevelFieldName`: Can be set to customize level field name.
* `zerolog.MessageFieldName`: Can be set to customize message field name. * `zerolog.MessageFieldName`: Can be set to customize message field name.

View File

@ -6,27 +6,7 @@ import (
"time" "time"
) )
var ( var now = time.Now
// TimestampFieldName is the field name used for the timestamp field.
TimestampFieldName = "time"
// LevelFieldName is the field name used for the level field.
LevelFieldName = "level"
// MessageFieldName is the field name used for the message field.
MessageFieldName = "message"
// ErrorFieldName is the field name used for error fields.
ErrorFieldName = "error"
// SampleFieldName is the name of the field used to report sampling.
SampleFieldName = "sample"
// TimeFieldFormat defines the time format of the Time field type.
TimeFieldFormat = time.RFC3339
now = time.Now
)
type FieldMode uint8 type FieldMode uint8

54
globals.go Normal file
View File

@ -0,0 +1,54 @@
package zerolog
import "time"
import "sync/atomic"
var (
// TimestampFieldName is the field name used for the timestamp field.
TimestampFieldName = "time"
// LevelFieldName is the field name used for the level field.
LevelFieldName = "level"
// MessageFieldName is the field name used for the message field.
MessageFieldName = "message"
// ErrorFieldName is the field name used for error fields.
ErrorFieldName = "error"
// SampleFieldName is the name of the field used to report sampling.
SampleFieldName = "sample"
// TimeFieldFormat defines the time format of the Time field type.
TimeFieldFormat = time.RFC3339
)
var (
gLevel = new(uint32)
disableSampling = new(uint32)
)
// SetGlobalLevel sets the global override for log level. If this
// values is raised, all Loggers will use at least this value.
//
// To globally disable logs, set GlobalLevel to Disabled.
func SetGlobalLevel(l Level) {
atomic.StoreUint32(gLevel, uint32(l))
}
func globalLevel() Level {
return Level(atomic.LoadUint32(gLevel))
}
// DisableSampling will disable sampling in all Loggers if true.
func DisableSampling(v bool) {
var i uint32
if v {
i = 1
}
atomic.StoreUint32(disableSampling, i)
}
func samplingDisabled() bool {
return atomic.LoadUint32(gLevel) == 1
}

17
log.go
View File

@ -30,7 +30,7 @@
// //
// Level logging // Level logging
// //
// zerolog.GlobalLevel = zerolog.InfoLevel // zerolog.SetGlobalLevel(zerolog.InfoLevel)
// //
// log.Debug().Msg("filtered out message") // log.Debug().Msg("filtered out message")
// log.Info().Msg("routed message") // log.Info().Msg("routed message")
@ -124,17 +124,6 @@ const (
Rarely = int64(1000) Rarely = int64(1000)
) )
var (
// GlobalLevel defines the global override for log level. If this
// values is raised, all Loggers will use at least this value.
//
// To globally disable logs, set GlobalLevel to Disabled.
GlobalLevel = DebugLevel
// DisableSampling will disable sampling in all Loggers if true.
DisableSampling = false
)
// A Logger represents an active logging object that generates lines // A Logger represents an active logging object that generates lines
// of JSON output to an io.Writer. Each logging operation makes a single // of JSON output to an io.Writer. Each logging operation makes a single
// call to the Writer's Write method. There is no guaranty on access // call to the Writer's Write method. There is no guaranty on access
@ -270,10 +259,10 @@ func (l Logger) newEvent(level Level, addLevelField bool, done func(string)) Eve
// should returns true if the log event should be logged. // should returns true if the log event should be logged.
func (l Logger) should(lvl Level) bool { func (l Logger) should(lvl Level) bool {
if lvl < l.level || lvl < GlobalLevel { if lvl < l.level || lvl < globalLevel() {
return false return false
} }
if !DisableSampling && l.sample > 0 && l.counter != nil { if l.sample > 0 && l.counter != nil && !samplingDisabled() {
c := atomic.AddUint32(l.counter, 1) c := atomic.AddUint32(l.counter, 1)
return c%l.sample == 0 return c%l.sample == 0
} }