add an ability to set levels separately for named loggers
with glob support
This commit is contained in:
parent
5e6199d106
commit
77d8c739f2
@ -1,11 +1,17 @@
|
|||||||
package logger
|
package logger
|
||||||
|
|
||||||
import "go.uber.org/zap"
|
import (
|
||||||
|
"go.uber.org/zap"
|
||||||
|
|
||||||
|
"github.com/anytypeio/any-sync/util/slice"
|
||||||
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Production bool `yaml:"production"`
|
Production bool `yaml:"production"`
|
||||||
DefaultLevel string `yaml:"defaultLevel"`
|
DefaultLevel string `yaml:"defaultLevel"`
|
||||||
NamedLevels map[string]string `yaml:"namedLevels"`
|
NamedLevels map[string]string `yaml:"namedLevels"`
|
||||||
|
AddOutputPaths []string
|
||||||
|
DisableStdErr bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l Config) ApplyGlobal() {
|
func (l Config) ApplyGlobal() {
|
||||||
@ -15,19 +21,33 @@ func (l Config) ApplyGlobal() {
|
|||||||
} else {
|
} else {
|
||||||
conf = zap.NewDevelopmentConfig()
|
conf = zap.NewDevelopmentConfig()
|
||||||
}
|
}
|
||||||
|
if len(l.AddOutputPaths) > 0 {
|
||||||
|
conf.OutputPaths = append(conf.OutputPaths, l.AddOutputPaths...)
|
||||||
|
}
|
||||||
|
if l.DisableStdErr {
|
||||||
|
conf.OutputPaths = slice.Filter(conf.OutputPaths, func(path string) bool {
|
||||||
|
return path != "stderr"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
if defaultLevel, err := zap.ParseAtomicLevel(l.DefaultLevel); err == nil {
|
if defaultLevel, err := zap.ParseAtomicLevel(l.DefaultLevel); err == nil {
|
||||||
conf.Level = defaultLevel
|
conf.Level = defaultLevel
|
||||||
}
|
}
|
||||||
var levels = make(map[string]zap.AtomicLevel)
|
var lvl = make(map[string]zap.AtomicLevel)
|
||||||
for k, v := range l.NamedLevels {
|
for k, v := range l.NamedLevels {
|
||||||
if lev, err := zap.ParseAtomicLevel(v); err != nil {
|
if lev, err := zap.ParseAtomicLevel(v); err == nil {
|
||||||
levels[k] = lev
|
lvl[k] = lev
|
||||||
|
// we need to have a minimum level of all named loggers for the main logger
|
||||||
|
if lev.Level() < conf.Level.Level() {
|
||||||
|
conf.Level.SetLevel(lev.Level())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
defaultLogger, err := conf.Build()
|
lg, err := conf.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Default().Fatal("can't build logger", zap.Error(err))
|
Default().Fatal("can't build logger", zap.Error(err))
|
||||||
}
|
}
|
||||||
SetDefault(defaultLogger)
|
SetDefault(lg)
|
||||||
SetNamedLevels(levels)
|
SetNamedLevels(lvl)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,51 +1,110 @@
|
|||||||
package logger
|
package logger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go.uber.org/zap"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/gobwas/glob"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
defaultLogger *zap.Logger
|
logger *zap.Logger
|
||||||
levels = make(map[string]zap.AtomicLevel)
|
loggerConfig zap.Config
|
||||||
loggers = make(map[string]CtxLogger)
|
namedLevels = make(map[string]zap.AtomicLevel)
|
||||||
|
namedGlobs = make(map[string]glob.Glob)
|
||||||
|
namedLoggers = make(map[string]CtxLogger)
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
defaultLogger, _ = zap.NewDevelopment()
|
loggerConfig = zap.NewDevelopmentConfig()
|
||||||
zap.NewProduction()
|
logger, _ = loggerConfig.Build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetDefault replaces the default logger
|
||||||
|
// you need to call SetNamedLevels after in case you have named loggers,
|
||||||
|
// otherwise they will use the old logger
|
||||||
func SetDefault(l *zap.Logger) {
|
func SetDefault(l *zap.Logger) {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
defer mu.Unlock()
|
defer mu.Unlock()
|
||||||
*defaultLogger = *l
|
*logger = *l
|
||||||
for name, l := range loggers {
|
|
||||||
*l.Logger = *defaultLogger.Named(name)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetNamedLevels sets the namedLevels for named loggers
|
||||||
|
// it also supports glob patterns for names, like "app*"
|
||||||
|
// can be racy in case there are existing named loggers
|
||||||
|
// so consider to call only once at the beginning
|
||||||
func SetNamedLevels(l map[string]zap.AtomicLevel) {
|
func SetNamedLevels(l map[string]zap.AtomicLevel) {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
defer mu.Unlock()
|
defer mu.Unlock()
|
||||||
levels = l
|
namedLevels = l
|
||||||
|
|
||||||
|
var minLevel = logger.Level()
|
||||||
|
for k, l := range namedLevels {
|
||||||
|
g, err := glob.Compile(k)
|
||||||
|
if err == nil {
|
||||||
|
namedGlobs[k] = g
|
||||||
|
}
|
||||||
|
namedLevels[k] = l
|
||||||
|
if l.Level() < minLevel {
|
||||||
|
minLevel = l.Level()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if minLevel < logger.Level() {
|
||||||
|
// recreate logger if the min level is lower than the current min one
|
||||||
|
loggerConfig.Level = zap.NewAtomicLevelAt(minLevel)
|
||||||
|
logger, _ = loggerConfig.Build()
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, lg := range namedLoggers {
|
||||||
|
level := getLevel(name)
|
||||||
|
// this can be racy, but
|
||||||
|
lg.Logger = zap.New(logger.Core()).WithOptions(
|
||||||
|
zap.IncreaseLevel(level),
|
||||||
|
).Named(name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Default() *zap.Logger {
|
func Default() *zap.Logger {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
defer mu.Unlock()
|
defer mu.Unlock()
|
||||||
return defaultLogger
|
return logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLevel(name string) zap.AtomicLevel {
|
||||||
|
level, ok := namedLevels[name]
|
||||||
|
if !ok {
|
||||||
|
var found bool
|
||||||
|
for globName, glob := range namedGlobs {
|
||||||
|
if glob.Match(name) {
|
||||||
|
found = true
|
||||||
|
level, _ = namedLevels[globName]
|
||||||
|
// no need to check ok, because we know that globName exists
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
level = loggerConfig.Level
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return level
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNamed(name string, fields ...zap.Field) CtxLogger {
|
func NewNamed(name string, fields ...zap.Field) CtxLogger {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
defer mu.Unlock()
|
defer mu.Unlock()
|
||||||
l := defaultLogger.Named(name)
|
|
||||||
if len(fields) > 0 {
|
if l, nameExists := namedLoggers[name]; nameExists {
|
||||||
l = l.With(fields...)
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
level := getLevel(name)
|
||||||
|
l := zap.New(logger.Core()).WithOptions(
|
||||||
|
zap.IncreaseLevel(level),
|
||||||
|
).Named(name)
|
||||||
|
|
||||||
ctxL := CtxLogger{l}
|
ctxL := CtxLogger{l}
|
||||||
loggers[name] = ctxL
|
namedLoggers[name] = ctxL
|
||||||
return ctxL
|
return ctxL
|
||||||
}
|
}
|
||||||
|
|||||||
3
go.mod
3
go.mod
@ -7,6 +7,7 @@ require (
|
|||||||
github.com/awalterschulze/gographviz v2.0.3+incompatible
|
github.com/awalterschulze/gographviz v2.0.3+incompatible
|
||||||
github.com/cespare/xxhash v1.1.0
|
github.com/cespare/xxhash v1.1.0
|
||||||
github.com/cheggaaa/mb/v3 v3.0.1
|
github.com/cheggaaa/mb/v3 v3.0.1
|
||||||
|
github.com/gobwas/glob v0.2.3
|
||||||
github.com/goccy/go-graphviz v0.1.0
|
github.com/goccy/go-graphviz v0.1.0
|
||||||
github.com/gogo/protobuf v1.3.2
|
github.com/gogo/protobuf v1.3.2
|
||||||
github.com/golang/mock v1.6.0
|
github.com/golang/mock v1.6.0
|
||||||
@ -22,6 +23,7 @@ require (
|
|||||||
github.com/ipfs/go-unixfs v0.4.4
|
github.com/ipfs/go-unixfs v0.4.4
|
||||||
github.com/libp2p/go-libp2p v0.24.1
|
github.com/libp2p/go-libp2p v0.24.1
|
||||||
github.com/minio/sha256-simd v1.0.0
|
github.com/minio/sha256-simd v1.0.0
|
||||||
|
github.com/mr-tron/base58 v1.2.0
|
||||||
github.com/multiformats/go-multibase v0.1.1
|
github.com/multiformats/go-multibase v0.1.1
|
||||||
github.com/multiformats/go-multihash v0.2.1
|
github.com/multiformats/go-multihash v0.2.1
|
||||||
github.com/prometheus/client_golang v1.14.0
|
github.com/prometheus/client_golang v1.14.0
|
||||||
@ -74,7 +76,6 @@ require (
|
|||||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||||
github.com/mattn/go-pointer v0.0.1 // indirect
|
github.com/mattn/go-pointer v0.0.1 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||||
github.com/mr-tron/base58 v1.2.0 // indirect
|
|
||||||
github.com/multiformats/go-base32 v0.1.0 // indirect
|
github.com/multiformats/go-base32 v0.1.0 // indirect
|
||||||
github.com/multiformats/go-base36 v0.2.0 // indirect
|
github.com/multiformats/go-base36 v0.2.0 // indirect
|
||||||
github.com/multiformats/go-multiaddr v0.8.0 // indirect
|
github.com/multiformats/go-multiaddr v0.8.0 // indirect
|
||||||
|
|||||||
2
go.sum
2
go.sum
@ -106,6 +106,8 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
|||||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
|
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
|
||||||
|
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||||
|
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||||
github.com/goccy/go-graphviz v0.1.0 h1:6OqQoQ5PeAiHYe/YcusyeulqBrOkUb16HQ4ctRdyVUU=
|
github.com/goccy/go-graphviz v0.1.0 h1:6OqQoQ5PeAiHYe/YcusyeulqBrOkUb16HQ4ctRdyVUU=
|
||||||
github.com/goccy/go-graphviz v0.1.0/go.mod h1:wXVsXxmyMQU6TN3zGRttjNn3h+iCAS7xQFC6TlNvLhk=
|
github.com/goccy/go-graphviz v0.1.0/go.mod h1:wXVsXxmyMQU6TN3zGRttjNn3h+iCAS7xQFC6TlNvLhk=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user