You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

236 lines
5.5 KiB

package log
import (
"errors"
"fmt"
"io/fs"
"io/ioutil"
"log"
"os"
"path"
"time"
"github.com/BurntSushi/toml"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"gopkg.in/yaml.v2"
)
var (
logger Logger
)
type YLogger struct {
Logger
dynamicLevel zap.AtomicLevel
}
type Logger interface {
Info(args ...interface{})
Warn(args ...interface{})
Error(args ...interface{})
Debug(args ...interface{})
Infof(fmt string, args ...interface{})
Warnf(fmt string, args ...interface{})
Errorf(fmt string, args ...interface{})
Debugf(fmt string, args ...interface{})
}
func init() {
var (
cfg LogCfg
logCfg GlobalCfg
)
log.Println("config file name -->", ConfigFile)
log.Println("starting ...")
if _, err := toml.DecodeFile(ConfigFile, &logCfg); err != nil {
//log.Fatalf("Read config file err:%s", err.Error())
log.Println("failed to open config file")
if err = InitLog("", cfg); nil != err {
log.Println(err.Error())
}
return
}
cfg = logCfg.Logs
cfg.OutputPaths = cfg.LogPath + cfg.APPName + time.Now().Format("2006-01-02") + ".log"
cfg.ErrorOutputPaths = cfg.LogPath + cfg.APPName + ".error"
err := InitLog(cfg.LogConf, cfg)
if err != nil {
log.Printf("[InitLog] warn: %v", err)
}
}
func ReloadLogger(configFile string) {
var (
cfg LogCfg
logCfg GlobalCfg
)
log.Println("config file name -->", configFile)
if _, err := toml.DecodeFile(configFile, &logCfg); err != nil {
log.Fatalf("Read config file err:%s", err.Error())
}
cfg = logCfg.Logs
cfg.OutputPaths = cfg.LogPath + cfg.APPName + time.Now().Format("2006-01-02") + ".log"
cfg.ErrorOutputPaths = cfg.LogPath + cfg.APPName + ".error"
err := InitLog(cfg.LogConf, cfg)
if err != nil {
log.Printf("[ReloadLogger] warn: %v", err)
}
}
func RotateLogger(cfg LogCfg) {
cfg.OutputPaths = cfg.LogInfoPath + cfg.APPName + ".log"
cfg.ErrorOutputPaths = cfg.LogErrPath + cfg.APPName + ".error"
if _, err := os.Stat(cfg.OutputPaths); errors.Is(err, fs.ErrNotExist) {
if _, err = os.Create(cfg.OutputPaths); nil != err {
log.Printf("[RotateLogger] error: %s", err.Error())
return
}
}
//if _, err := os.Stat(cfg.ErrorOutputPaths); errors.Is(err, fs.ErrNotExist) {
// if _, err = os.Create(cfg.ErrorOutputPaths); nil != err {
// log.Printf("[RotateLogger] error: %s", err.Error())
// return
// }
//}
err := InitLog(cfg.LogConf, cfg)
if err != nil {
log.Printf("[RotateLogger] warn: %v", err)
}
}
var defaultZapConfig = []byte(`
level: "info"
development: false
disableCaller: false
disableStacktrace: false
sampling:
encoding: "console"
# encoder
encoderConfig:
messageKey: "message"
levelKey: "level"
timeKey: "time"
nameKey: "logger"
callerKey: "caller"
stacktraceKey: "stacktrace"
lineEnding: ""
# levelEncoder: "capitalColor"
timeEncoder: "iso8601"
durationEncoder: "seconds"
callerEncoder: "short"
nameEncoder: ""
`)
func InitLog(logConfFile string, cfg LogCfg) error {
conf := &zap.Config{}
if logConfFile != "" {
if path.Ext(logConfFile) != ".yml" {
InitLogger(nil)
return fmt.Errorf("log configure file name{%s} suffix must be .yml", logConfFile)
}
confFileStream, err := ioutil.ReadFile(logConfFile)
if err != nil {
InitLogger(nil)
return fmt.Errorf("ioutil.ReadFile(file:%s) = error:%v", logConfFile, err)
}
err = yaml.Unmarshal(confFileStream, conf)
if err != nil {
InitLogger(nil)
return fmt.Errorf("[Unmarshal]init logger error: %v", err)
}
} else {
conf = &zap.Config{
Level: zap.NewAtomicLevel(),
Development: false,
DisableCaller: false,
DisableStacktrace: false,
Sampling: nil,
Encoding: "console",
EncoderConfig: zapcore.EncoderConfig{
MessageKey: "message",
LevelKey: "level",
TimeKey: "time",
NameKey: "logger",
CallerKey: "caller",
StacktraceKey: "stacktrace",
EncodeTime: zapcore.EpochMillisTimeEncoder,
EncodeDuration: zapcore.SecondsDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
EncodeName: nil,
EncodeLevel: nil,
},
}
err := yaml.Unmarshal(defaultZapConfig, conf)
if err != nil {
InitLogger(nil)
return fmt.Errorf("[Unmarshal]init logger error: %v", err)
}
}
conf.OutputPaths = append(conf.OutputPaths, cfg.OutputPaths)
conf.ErrorOutputPaths = append(conf.ErrorOutputPaths, cfg.ErrorOutputPaths)
InitLogger(conf)
return nil
}
func InitLogger(conf *zap.Config) {
var zapLoggerConfig zap.Config
if conf == nil {
zapLoggerConfig = zap.NewDevelopmentConfig()
zapLoggerEncoderConfig := zapcore.EncoderConfig{
TimeKey: "time",
LevelKey: "level",
NameKey: "logger",
CallerKey: "caller",
MessageKey: "message",
StacktraceKey: "stacktrace",
EncodeTime: zapcore.ISO8601TimeEncoder,
EncodeDuration: zapcore.SecondsDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
}
zapLoggerConfig.EncoderConfig = zapLoggerEncoderConfig
} else {
zapLoggerConfig = *conf
}
zapLogger, _ := zapLoggerConfig.Build(zap.AddCallerSkip(1))
//logger = zapLogger.Sugar()
logger = &YLogger{Logger: zapLogger.Sugar(), dynamicLevel: zapLoggerConfig.Level}
}
func SetLogger(log Logger) {
logger = log
}
func GetLogger() Logger {
return logger
}
func SetLoggerLevel(level string) bool {
if l, ok := logger.(OpsLogger); ok {
l.SetLoggerLevel(level)
return true
}
return false
}
type OpsLogger interface {
Logger
SetLoggerLevel(level string)
}
func (dl *YLogger) SetLoggerLevel(level string) {
l := new(zapcore.Level)
l.Set(level)
dl.dynamicLevel.SetLevel(*l)
}