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

142 lines
4.3 KiB
Go

package logger
import (
"github.com/natefinch/lumberjack"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"os"
"path/filepath"
)
var Log *zap.Logger
var SLog *zap.SugaredLogger
const DefaultLogPath = "/logs"
type (
// FileConfig 日志文件配置
FileConfig struct {
Level string // 日志打印级别 debug info warning error
Format string // 输出日志格式 console, json
Enabled bool // 是否开启
Path string // 输出日志文件路径
FileName string // 输出日志文件名称
FileMaxSize int // 【日志分割】单个日志文件最多存储量 单位(mb)
FileMaxBackups int // 【日志分割】日志备份文件最多数量
MaxAge int // 日志保留时间,单位: 天 (day)
Compress bool // 是否压缩日志
}
// ConsoleConfig 控制台日志配置
ConsoleConfig struct {
Level string // 日志打印级别 debug info warning error
Format string // 输出日志格式 console, json
}
)
var logLevel = map[string]zapcore.Level{
"debug": zapcore.DebugLevel,
"info": zapcore.InfoLevel,
"warn": zapcore.WarnLevel,
"error": zapcore.ErrorLevel,
}
func Sync() {
if SLog != nil {
_ = SLog.Sync()
}
if Log != nil {
_ = Log.Sync()
}
}
// InitLogger 初始化 log
func InitLogger(fileConf *FileConfig, consoleConf *ConsoleConfig) error {
cores := make([]zapcore.Core, 0, 2)
consoleCore := zapcore.NewCore(getEncoder(consoleConf), zapcore.AddSync(os.Stdout), getLogLevel(consoleConf.Level))
cores = append(cores, consoleCore)
if fileConf.Enabled {
writeSyncer, err := getLogWriter(fileConf) // 日志文件配置 文件位置和切割
if err != nil {
return err
}
fileCore := zapcore.NewCore(getEncoder(fileConf), writeSyncer, getLogLevel(fileConf.Level))
cores = append(cores, fileCore)
}
// 控制台/文件 配置分离
core := zapcore.NewTee(cores...)
logger := zap.New(core, zap.AddCaller()) //zap.AddCaller() 输出日志打印文件和行数如: logger/logger_test.go:33
SLog = logger.Sugar()
Log = logger
return nil
}
// getLogLevel 获取日志打印级别
func getLogLevel(level string) zapcore.Level {
l, ok := logLevel[level] // 日志打印级别
if !ok {
l = logLevel["info"]
}
return l
}
// getLogWriter 获取日志输出方式 日志文件 控制台
func getLogWriter(conf *FileConfig) (zapcore.WriteSyncer, error) {
// 判断日志路径是否存在,如果不存在就创建
if conf.Path == "" {
conf.Path = getCurrentAbPath() + DefaultLogPath
}
if exist := isExist(conf.Path); !exist {
if err := os.MkdirAll(conf.Path, os.ModePerm); err != nil {
conf.Path = getCurrentAbPath() + DefaultLogPath
if err := os.MkdirAll(conf.Path, os.ModePerm); err != nil {
return nil, err
}
}
}
// 日志文件 与 日志切割 配置
lumberJackLogger := &lumberjack.Logger{
Filename: filepath.Join(conf.Path, conf.FileName), // 日志文件路径
MaxSize: conf.FileMaxSize, // 单个日志文件最大多少 mb
MaxBackups: conf.FileMaxBackups, // 日志备份数量
MaxAge: conf.MaxAge, // 日志最长保留时间
Compress: conf.Compress, // 是否压缩日志
}
return zapcore.AddSync(lumberJackLogger), nil
}
// getEncoder 编码器(如何写入日志)
func getEncoder(conf interface{}) zapcore.Encoder {
encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05.000Z07") // log 时间格式 例如: 2021-09-11t20:05:54.852+0800
encoderConfig.EncodeCaller = zapcore.FullCallerEncoder
var format string
switch conf.(type) {
case FileConfig:
format = conf.(FileConfig).Format
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
case ConsoleConfig:
format = conf.(ConsoleConfig).Format
// 输出level序列化为全大写字符串如 INFO DEBUG ERROR 彩色
encoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
}
if format == "json" {
return zapcore.NewJSONEncoder(encoderConfig) // 以json格式写入
}
return zapcore.NewConsoleEncoder(encoderConfig) // 以默认console格式写入
}
// isExist 判断文件或者目录是否存在
func isExist(path string) bool {
_, err := os.Stat(path)
return err == nil || os.IsExist(err)
}