|
@@ -0,0 +1,104 @@
|
|
|
|
|
+// Pacage logger provides a simple wrapper around zap logger
|
|
|
|
|
+package logger
|
|
|
|
|
+
|
|
|
|
|
+import (
|
|
|
|
|
+ "fmt"
|
|
|
|
|
+ "os"
|
|
|
|
|
+ "strings"
|
|
|
|
|
+ "time"
|
|
|
|
|
+
|
|
|
|
|
+ "github.com/runningwater/gohub/pkg/app"
|
|
|
|
|
+ "go.uber.org/zap"
|
|
|
|
|
+ "go.uber.org/zap/zapcore"
|
|
|
|
|
+ "gopkg.in/natefinch/lumberjack.v2"
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
|
|
+// Logger 全局日志对象
|
|
|
|
|
+var Logger *zap.Logger
|
|
|
|
|
+
|
|
|
|
|
+// Init 初始化日志
|
|
|
|
|
+func Init(filename string, maxSize, maxBackup, maxAge int, compress bool, logType, level string) {
|
|
|
|
|
+ // 获取日志写入介质
|
|
|
|
|
+ writeSyncer := getLogWriter(filename, maxSize, maxBackup, maxAge, compress, logType)
|
|
|
|
|
+ // 设置日志等级, 具体见 config/log.go
|
|
|
|
|
+ logLevel := new(zap.AtomicLevel)
|
|
|
|
|
+ if err := logLevel.UnmarshalText([]byte(level)); err != nil {
|
|
|
|
|
+ fmt.Println("日志初始化错误,日志级别设置有误。请修改 config/log.go 中的 log.level")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 初始化 core
|
|
|
|
|
+ core := zapcore.NewCore(getEncoder(), writeSyncer, logLevel)
|
|
|
|
|
+ // 初始化 logger
|
|
|
|
|
+ Logger = zap.New(core,
|
|
|
|
|
+ zap.AddCaller(), // 调用文件和行号,内部使用 runtime.Caller
|
|
|
|
|
+ zap.AddCallerSkip(1), // 调用文件和行号,内部使用 runtime.Caller
|
|
|
|
|
+ zap.Development(), // 开发模式,堆栈跟踪
|
|
|
|
|
+ zap.AddStacktrace(zapcore.ErrorLevel), // 记录错误级别以上的堆栈信息
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ // 设置全局 logger
|
|
|
|
|
+ // 将自定义的 logger 替换 zap 的全局 logger
|
|
|
|
|
+ zap.ReplaceGlobals(Logger)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// getEncoder 获取编码器(如何写入日志), 输出: 日志格式
|
|
|
|
|
+func getEncoder() zapcore.Encoder {
|
|
|
|
|
+ // 日志模式规则
|
|
|
|
|
+ encoderConfig := zapcore.EncoderConfig{
|
|
|
|
|
+ TimeKey: "time", // 时间字段名
|
|
|
|
|
+ LevelKey: "level", // 日志级别字段名
|
|
|
|
|
+ NameKey: "logger", // 日志名称字段名
|
|
|
|
|
+ CallerKey: "caller", // 调用者字段名
|
|
|
|
|
+ FunctionKey: zapcore.OmitKey, // 函数名字段名,不显示
|
|
|
|
|
+ MessageKey: "msg", // 消息字段名
|
|
|
|
|
+ StacktraceKey: "stacktrace", // 堆栈跟踪字段名
|
|
|
|
|
+ LineEnding: zapcore.DefaultLineEnding, // 每行日志的结尾添加换行符
|
|
|
|
|
+ EncodeLevel: zapcore.CapitalLevelEncoder, // 大写编码器
|
|
|
|
|
+ EncodeTime: customTimeEncoder, // 自定义时间编码器
|
|
|
|
|
+ EncodeDuration: zapcore.SecondsDurationEncoder, // 以秒为单位显示持续时间
|
|
|
|
|
+ EncodeCaller: zapcore.ShortCallerEncoder, // 短路径编码器
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if app.IsLocal() {
|
|
|
|
|
+ encoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder // 彩色编码器
|
|
|
|
|
+ // 如果是本地环境,使用 console 编码器
|
|
|
|
|
+ return zapcore.NewConsoleEncoder(encoderConfig)
|
|
|
|
|
+ }
|
|
|
|
|
+ // 如果不是本地环境,使用 JSON 编码器
|
|
|
|
|
+ return zapcore.NewJSONEncoder(encoderConfig)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func customTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
|
|
|
|
|
+ // 自定义时间格式
|
|
|
|
|
+ enc.AppendString(t.Format("2006-01-02 15:04:05"))
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// getLogWriter 获取日志写入介质
|
|
|
|
|
+// os.Stdout: 标准输出
|
|
|
|
|
+// 文件输出
|
|
|
|
|
+func getLogWriter(filename string, maxSize, maxBackup, maxAge int, compress bool, logType string) zapcore.WriteSyncer {
|
|
|
|
|
+ // 如果配置了按日期记录日志,则使用按日期记录日志
|
|
|
|
|
+ if logType == "daily" {
|
|
|
|
|
+ logname := time.Now().Format("2006-01-02") + ".log"
|
|
|
|
|
+ filename = strings.Replace(filename, "logs.log", logname, 1)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 滚动日志,详见 config/log.go
|
|
|
|
|
+ lumberJackLogger := &lumberjack.Logger{
|
|
|
|
|
+ Filename: filename, // 日志文件名
|
|
|
|
|
+ MaxSize: maxSize, // 每个日志文件保存的最大尺寸 单位:MB
|
|
|
|
|
+ MaxBackups: maxBackup, // 日志文件最多保存多少个备份
|
|
|
|
|
+ MaxAge: maxAge, // 文件最多保存多少天
|
|
|
|
|
+ Compress: compress, // 是否压缩
|
|
|
|
|
+ }
|
|
|
|
|
+ if app.IsLocal() {
|
|
|
|
|
+ // 如果是本地环境,使用标准输出和文件输出
|
|
|
|
|
+ return zapcore.NewMultiWriteSyncer(
|
|
|
|
|
+ zapcore.AddSync(os.Stdout),
|
|
|
|
|
+ zapcore.AddSync(lumberJackLogger),
|
|
|
|
|
+ )
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 生产环境只记录文件
|
|
|
|
|
+ return zapcore.AddSync(lumberJackLogger)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|