1 Star 0 Fork 0

小庄 / fabric

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
loggerlevels.go 4.78 KB
一键复制 编辑 原始数据 按行查看 历史
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package flogging
import (
"fmt"
"regexp"
"sort"
"strings"
"sync"
"github.com/pkg/errors"
"go.uber.org/zap/zapcore"
)
// LoggerLevels tracks the logging level of named loggers.
type LoggerLevels struct {
mutex sync.RWMutex
levelCache map[string]zapcore.Level
specs map[string]zapcore.Level
defaultLevel zapcore.Level
minLevel zapcore.Level
}
// DefaultLevel returns the default logging level for loggers that do not have
// an explicit level set.
func (l *LoggerLevels) DefaultLevel() zapcore.Level {
l.mutex.RLock()
lvl := l.defaultLevel
l.mutex.RUnlock()
return lvl
}
// ActivateSpec is used to modify logging levels.
//
// The logging specification has the following form:
// [<logger>[,<logger>...]=]<level>[:[<logger>[,<logger>...]=]<level>...]
func (l *LoggerLevels) ActivateSpec(spec string) error {
l.mutex.Lock()
defer l.mutex.Unlock()
defaultLevel := zapcore.InfoLevel
specs := map[string]zapcore.Level{}
for _, field := range strings.Split(spec, ":") {
split := strings.Split(field, "=")
switch len(split) {
case 1: // level
if field != "" && !IsValidLevel(field) {
return errors.Errorf("invalid logging specification '%s': bad segment '%s'", spec, field)
}
defaultLevel = NameToLevel(field)
case 2: // <logger>[,<logger>...]=<level>
if split[0] == "" {
return errors.Errorf("invalid logging specification '%s': no logger specified in segment '%s'", spec, field)
}
if field != "" && !IsValidLevel(split[1]) {
return errors.Errorf("invalid logging specification '%s': bad segment '%s'", spec, field)
}
level := NameToLevel(split[1])
loggers := strings.Split(split[0], ",")
for _, logger := range loggers {
// check if the logger name in the spec is valid. The
// trailing period is trimmed as logger names in specs
// ending with a period signifies that this part of the
// spec refers to the exact logger name (i.e. is not a prefix)
if !isValidLoggerName(strings.TrimSuffix(logger, ".")) {
return errors.Errorf("invalid logging specification '%s': bad logger name '%s'", spec, logger)
}
specs[logger] = level
}
default:
return errors.Errorf("invalid logging specification '%s': bad segment '%s'", spec, field)
}
}
minLevel := defaultLevel
for _, lvl := range specs {
if lvl < minLevel {
minLevel = lvl
}
}
l.minLevel = minLevel
l.defaultLevel = defaultLevel
l.specs = specs
l.levelCache = map[string]zapcore.Level{}
return nil
}
// logggerNameRegexp defines the valid logger names
var loggerNameRegexp = regexp.MustCompile(`^[[:alnum:]_#:-]+(\.[[:alnum:]_#:-]+)*$`)
// isValidLoggerName checks whether a logger name contains only valid
// characters. Names that begin/end with periods or contain special
// characters (other than periods, underscores, pound signs, colons
// and dashes) are invalid.
func isValidLoggerName(loggerName string) bool {
return loggerNameRegexp.MatchString(loggerName)
}
// Level returns the effective logging level for a logger. If a level has not
// been explicitly set for the logger, the default logging level will be
// returned.
func (l *LoggerLevels) Level(loggerName string) zapcore.Level {
if level, ok := l.cachedLevel(loggerName); ok {
return level
}
l.mutex.Lock()
level := l.calculateLevel(loggerName)
l.levelCache[loggerName] = level
l.mutex.Unlock()
return level
}
// calculateLevel walks the logger name back to find the appropriate
// log level from the current spec.
func (l *LoggerLevels) calculateLevel(loggerName string) zapcore.Level {
candidate := loggerName + "."
for {
if lvl, ok := l.specs[candidate]; ok {
return lvl
}
idx := strings.LastIndex(candidate, ".")
if idx <= 0 {
return l.defaultLevel
}
candidate = candidate[:idx]
}
}
// cachedLevel attempts to retrieve the effective log level for a logger from the
// cache. If the logger is not found, ok will be false.
func (l *LoggerLevels) cachedLevel(loggerName string) (lvl zapcore.Level, ok bool) {
l.mutex.RLock()
level, ok := l.levelCache[loggerName]
l.mutex.RUnlock()
return level, ok
}
// Spec returns a normalized version of the active logging spec.
func (l *LoggerLevels) Spec() string {
l.mutex.RLock()
defer l.mutex.RUnlock()
var fields []string
for k, v := range l.specs {
fields = append(fields, fmt.Sprintf("%s=%s", k, v))
}
sort.Strings(fields)
fields = append(fields, l.defaultLevel.String())
return strings.Join(fields, ":")
}
// Enabled function is an enabled check that evaluates the minimum active logging level.
// It serves as a fast check before the (relatively) expensive Check call in the core.
func (l *LoggerLevels) Enabled(lvl zapcore.Level) bool {
l.mutex.RLock()
enabled := l.minLevel.Enabled(lvl)
l.mutex.RUnlock()
return enabled
}
1
https://gitee.com/zhuanglicheng/fabric.git
git@gitee.com:zhuanglicheng/fabric.git
zhuanglicheng
fabric
fabric
v2.1.1

搜索帮助