|
|
@ -8,21 +8,44 @@ import ( |
|
|
|
"runtime" |
|
|
|
) |
|
|
|
|
|
|
|
type logger struct { |
|
|
|
logger *zap.Logger |
|
|
|
level *zap.AtomicLevel |
|
|
|
sugar *zap.SugaredLogger |
|
|
|
var project string // project absolute path
|
|
|
|
var logger *logCore // singleton logger handle
|
|
|
|
|
|
|
|
// logChannel handle multiple writers with unified format.
|
|
|
|
type logChannel struct { |
|
|
|
encoder zapcore.Encoder |
|
|
|
writers []zapcore.WriteSyncer |
|
|
|
stderr zapcore.Core // fixed stderr output
|
|
|
|
} |
|
|
|
|
|
|
|
// logCore manage log level, channels and other interfaces.
|
|
|
|
type logCore struct { |
|
|
|
prefix string // custom output prefix
|
|
|
|
path string // project absolute path
|
|
|
|
verbose bool // show goroutine id and caller line
|
|
|
|
verbose bool // show verbose information
|
|
|
|
|
|
|
|
plain logChannel // log channel with plain text
|
|
|
|
colored logChannel // log channel with colored text
|
|
|
|
|
|
|
|
level *zap.AtomicLevel // zap log level pointer
|
|
|
|
entry *zap.SugaredLogger // zap sugared logger entry
|
|
|
|
} |
|
|
|
|
|
|
|
var logHandle *logger // singleton logger handle
|
|
|
|
func init() { |
|
|
|
_, src, _, _ := runtime.Caller(0) // absolute path of current code
|
|
|
|
project = path.Join(path.Dir(src), "../") |
|
|
|
|
|
|
|
zapLevel := zap.NewAtomicLevelAt(InfoLevel) // using info level in default
|
|
|
|
logger = &logCore{ |
|
|
|
verbose: false, |
|
|
|
level: &zapLevel, |
|
|
|
prefix: "[XProxy]", |
|
|
|
plain: buildChannel(false), |
|
|
|
colored: buildChannel(true), |
|
|
|
} |
|
|
|
logger.addColoredWrites(os.Stderr) // output into stderr in default
|
|
|
|
} |
|
|
|
|
|
|
|
// logConfig generates log config for XProxy.
|
|
|
|
func logConfig(colored bool) zapcore.EncoderConfig { |
|
|
|
// buildChannel generate logChannel with `colored` option.
|
|
|
|
func buildChannel(colored bool) logChannel { |
|
|
|
config := zapcore.EncoderConfig{ |
|
|
|
ConsoleSeparator: " ", |
|
|
|
MessageKey: "msg", |
|
|
@ -33,46 +56,40 @@ func logConfig(colored bool) zapcore.EncoderConfig { |
|
|
|
EncodeLevel: levelEncoder, |
|
|
|
EncodeCaller: callerEncoder, |
|
|
|
} |
|
|
|
if colored { |
|
|
|
if colored { // using colored version
|
|
|
|
config.EncodeTime = timeColoredEncoder |
|
|
|
config.EncodeLevel = levelColoredEncoder |
|
|
|
config.EncodeCaller = callerColoredEncoder |
|
|
|
} |
|
|
|
return config |
|
|
|
return logChannel{ |
|
|
|
encoder: zapcore.NewConsoleEncoder(config), |
|
|
|
writers: []zapcore.WriteSyncer{}, // without any writer
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func init() { |
|
|
|
zapLevel := zap.NewAtomicLevelAt(InfoLevel) // using info level in default
|
|
|
|
zapCore := zapcore.NewCore( |
|
|
|
zapcore.NewConsoleEncoder(logConfig(true)), // colorful output
|
|
|
|
zapcore.Lock(os.Stderr), |
|
|
|
zapLevel, |
|
|
|
// update refreshes the binding of the log core to the writers.
|
|
|
|
func (handle *logCore) update() { |
|
|
|
buildCore := func(channel *logChannel) zapcore.Core { // build zap core from logChannel
|
|
|
|
return zapcore.NewCore( |
|
|
|
channel.encoder, |
|
|
|
zap.CombineWriteSyncers(channel.writers...), |
|
|
|
handle.level, |
|
|
|
) |
|
|
|
zapLogger := zap.New(zapCore, zap.AddCaller(), zap.AddCallerSkip(1)) |
|
|
|
_, src, _, _ := runtime.Caller(0) // absolute path of current code
|
|
|
|
logHandle = &logger{ |
|
|
|
logger: zapLogger, |
|
|
|
level: &zapLevel, |
|
|
|
stderr: zapCore, |
|
|
|
sugar: zapLogger.Sugar(), |
|
|
|
writers: []zapcore.WriteSyncer{}, |
|
|
|
path: path.Join(path.Dir(src), "../"), |
|
|
|
prefix: "[XProxy]", |
|
|
|
verbose: false, |
|
|
|
} |
|
|
|
handle.entry = zap.New( |
|
|
|
zapcore.NewTee(buildCore(&handle.plain), buildCore(&handle.colored)), |
|
|
|
zap.AddCaller(), zap.AddCallerSkip(1), |
|
|
|
).Sugar() |
|
|
|
} |
|
|
|
|
|
|
|
// addWrites adds more plain log writers.
|
|
|
|
func addWrites(writers ...zapcore.WriteSyncer) { |
|
|
|
logHandle.writers = append(logHandle.writers, writers...) |
|
|
|
plainCore := zapcore.NewCore( |
|
|
|
zapcore.NewConsoleEncoder(logConfig(false)), // without colored
|
|
|
|
zap.CombineWriteSyncers(logHandle.writers...), |
|
|
|
logHandle.level, |
|
|
|
) |
|
|
|
logHandle.logger = zap.New( |
|
|
|
zapcore.NewTee(logHandle.stderr, plainCore), |
|
|
|
zap.AddCaller(), zap.AddCallerSkip(1), |
|
|
|
) |
|
|
|
logHandle.sugar = logHandle.logger.Sugar() |
|
|
|
// addPlainWrites adds plain text writers to the logCore.
|
|
|
|
func (handle *logCore) addPlainWrites(writers ...zapcore.WriteSyncer) { |
|
|
|
handle.plain.writers = append(handle.plain.writers, writers...) |
|
|
|
handle.update() |
|
|
|
} |
|
|
|
|
|
|
|
// addColoredWrites adds colored text writers to the logCore.
|
|
|
|
func (handle *logCore) addColoredWrites(writers ...zapcore.WriteSyncer) { |
|
|
|
handle.colored.writers = append(handle.colored.writers, writers...) |
|
|
|
handle.update() |
|
|
|
} |
|
|
|