1 Star 0 Fork 0

peter / fabric

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
logging.go 5.94 KB
一键复制 编辑 原始数据 按行查看 历史
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package flogging
import (
"fmt"
"io"
"os"
"sync"
"github.com/hyperledger/fabric/common/flogging/fabenc"
zaplogfmt "github.com/sykesm/zap-logfmt"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
// Config is used to provide dependencies to a Logging instance.
type Config struct {
// Format is the log record format specifier for the Logging instance. If the
// spec is the string "json", log records will be formatted as JSON. Any
// other string will be provided to the FormatEncoder. Please see
// fabenc.ParseFormat for details on the supported verbs.
//
// If Format is not provided, a default format that provides basic information will
// be used.
Format string
// LogSpec determines the log levels that are enabled for the logging system. The
// spec must be in a format that can be processed by ActivateSpec.
//
// If LogSpec is not provided, loggers will be enabled at the INFO level.
LogSpec string
// Writer is the sink for encoded and formatted log records.
//
// If a Writer is not provided, os.Stderr will be used as the log sink.
Writer io.Writer
}
// Logging maintains the state associated with the fabric logging system. It is
// intended to bridge between the legacy logging infrastructure built around
// go-logging and the structured, level logging provided by zap.
type Logging struct {
*LoggerLevels
mutex sync.RWMutex
encoding Encoding
encoderConfig zapcore.EncoderConfig
multiFormatter *fabenc.MultiFormatter
writer zapcore.WriteSyncer
observer Observer
}
// New creates a new logging system and initializes it with the provided
// configuration.
func New(c Config) (*Logging, error) {
encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.NameKey = "name"
l := &Logging{
LoggerLevels: &LoggerLevels{
defaultLevel: defaultLevel,
},
encoderConfig: encoderConfig,
multiFormatter: fabenc.NewMultiFormatter(),
}
err := l.Apply(c)
if err != nil {
return nil, err
}
return l, nil
}
// Apply applies the provided configuration to the logging system.
func (l *Logging) Apply(c Config) error {
err := l.SetFormat(c.Format)
if err != nil {
return err
}
if c.LogSpec == "" {
c.LogSpec = os.Getenv("FABRIC_LOGGING_SPEC")
}
if c.LogSpec == "" {
c.LogSpec = defaultLevel.String()
}
err = l.LoggerLevels.ActivateSpec(c.LogSpec)
if err != nil {
return err
}
if c.Writer == nil {
c.Writer = os.Stderr
}
l.SetWriter(c.Writer)
return nil
}
// SetFormat updates how log records are formatted and encoded. Log entries
// created after this method has completed will use the new format.
//
// An error is returned if the log format specification cannot be parsed.
func (l *Logging) SetFormat(format string) error {
l.mutex.Lock()
defer l.mutex.Unlock()
if format == "" {
format = defaultFormat
}
if format == "json" {
l.encoding = JSON
return nil
}
if format == "logfmt" {
l.encoding = LOGFMT
return nil
}
formatters, err := fabenc.ParseFormat(format)
if err != nil {
return err
}
l.multiFormatter.SetFormatters(formatters)
l.encoding = CONSOLE
return nil
}
// SetWriter controls which writer formatted log records are written to.
// Writers, with the exception of an *os.File, need to be safe for concurrent
// use by multiple go routines.
func (l *Logging) SetWriter(w io.Writer) io.Writer {
var sw zapcore.WriteSyncer
switch t := w.(type) {
case *os.File:
sw = zapcore.Lock(t)
case zapcore.WriteSyncer:
sw = t
default:
sw = zapcore.AddSync(w)
}
l.mutex.Lock()
ow := l.writer
l.writer = sw
l.mutex.Unlock()
return ow
}
// SetObserver is used to provide a log observer that will be called as log
// levels are checked or written.. Only a single observer is supported.
func (l *Logging) SetObserver(observer Observer) Observer {
l.mutex.Lock()
so := l.observer
l.observer = observer
l.mutex.Unlock()
return so
}
// Write satisfies the io.Write contract. It delegates to the writer argument
// of SetWriter or the Writer field of Config. The Core uses this when encoding
// log records.
func (l *Logging) Write(b []byte) (int, error) {
l.mutex.RLock()
w := l.writer
l.mutex.RUnlock()
return w.Write(b)
}
// Sync satisfies the zapcore.WriteSyncer interface. It is used by the Core to
// flush log records before terminating the process.
func (l *Logging) Sync() error {
l.mutex.RLock()
w := l.writer
l.mutex.RUnlock()
return w.Sync()
}
// Encoding satisfies the Encoding interface. It determines whether the JSON or
// CONSOLE encoder should be used by the Core when log records are written.
func (l *Logging) Encoding() Encoding {
l.mutex.RLock()
e := l.encoding
l.mutex.RUnlock()
return e
}
// ZapLogger instantiates a new zap.Logger with the specified name. The name is
// used to determine which log levels are enabled.
func (l *Logging) ZapLogger(name string) *zap.Logger {
if !isValidLoggerName(name) {
panic(fmt.Sprintf("invalid logger name: %s", name))
}
l.mutex.RLock()
core := &Core{
LevelEnabler: l.LoggerLevels,
Levels: l.LoggerLevels,
Encoders: map[Encoding]zapcore.Encoder{
JSON: zapcore.NewJSONEncoder(l.encoderConfig),
CONSOLE: fabenc.NewFormatEncoder(l.multiFormatter),
LOGFMT: zaplogfmt.NewEncoder(l.encoderConfig),
},
Selector: l,
Output: l,
Observer: l,
}
l.mutex.RUnlock()
return NewZapLogger(core).Named(name)
}
func (l *Logging) Check(e zapcore.Entry, ce *zapcore.CheckedEntry) {
l.mutex.RLock()
observer := l.observer
l.mutex.RUnlock()
if observer != nil {
observer.Check(e, ce)
}
}
func (l *Logging) WriteEntry(e zapcore.Entry, fields []zapcore.Field) {
l.mutex.RLock()
observer := l.observer
l.mutex.RUnlock()
if observer != nil {
observer.WriteEntry(e, fields)
}
}
// Logger instantiates a new FabricLogger with the specified name. The name is
// used to determine which log levels are enabled.
func (l *Logging) Logger(name string) *FabricLogger {
zl := l.ZapLogger(name)
return NewFabricLogger(zl)
}
1
https://gitee.com/peter_code_git/fabric.git
git@gitee.com:peter_code_git/fabric.git
peter_code_git
fabric
fabric
v2.1.1

搜索帮助