| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- // Pacage logger provides a simple wrapper around zap logger
- package logger
- import (
- "encoding/json"
- "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)
- }
- }
- // Dump 调试专用, 不会中断程序,会在终端打印 warning 信息。
- // 第一个参数会使用 json.Marshal 进行渲染,第二个参数可选
- //
- // logger.Dump(user.User{Name: "test"})
- // logger.Dump(user.User{Name: "test"}, "用户信息")
- func Dump(v any, msg ...string) {
- valueStr := jsonString(v)
- if len(msg) > 0 {
- Logger.Warn("Dump", zap.String(msg[0], valueStr))
- } else {
- Logger.Warn("Dump", zap.String("data", valueStr))
- }
- }
- // LogIf 当 err != nill 时记录 error 等级的日志
- func LogIf(err error) {
- if err != nil {
- Logger.Error("Error Occurred: ", zap.Error(err))
- }
- }
- // LogWarnIf 当 err != nill 时记录 warning 等级的日志
- func LogWarnIf(err error) {
- if err != nil {
- Logger.Warn("Error Occurred: ", zap.Error(err))
- }
- }
- // LogInfoIf 当 err != nill 时记录 info 等级的日志
- func LogInfoIf(err error) {
- if err != nil {
- Logger.Info("Error Occurred: ", zap.Error(err))
- }
- }
- // Debug 调试专用, 不会中断程序
- //
- // logger.Debug("Database", zap.String("sql", sql))
- func Debug(msg string, fields ...zap.Field) {
- Logger.Debug(msg, fields...)
- }
- // Info 信息级别
- func Info(msg string, fields ...zap.Field) {
- Logger.Info(msg, fields...)
- }
- // Warn 警告级别
- func Warn(msg string, fields ...zap.Field) {
- Logger.Warn(msg, fields...)
- }
- // Error 错误级别
- func Error(msg string, fields ...zap.Field) {
- Logger.Error(msg, fields...)
- }
- // Fatal 致命级别
- func Fatal(msg string, fields ...zap.Field) {
- Logger.Fatal(msg, fields...)
- }
- // DebugString 记录一条字符串类型的 debug 日志
- //
- // logger.DebugString("User", "name", "John")
- func DebugString(modeleName, name, msg string) {
- Logger.Debug(modeleName, zap.String(name, msg))
- }
- func InfoString(moduleName, name, msg string) {
- Logger.Info(moduleName, zap.String(name, msg))
- }
- func WarnString(moduleName, name, msg string) {
- Logger.Warn(moduleName, zap.String(name, msg))
- }
- func ErrorString(moduleName, name, msg string) {
- Logger.Error(moduleName, zap.String(name, msg))
- }
- func FatalString(moduleName, name, msg string) {
- Logger.Fatal(moduleName, zap.String(name, msg))
- }
- // DebugJSON 记录对象类型的 debug 日志,使用 json.Marshal 进行编码。调用示例:
- //
- // logger.DebugJSON("Auth", "读取登录用户", auth.CurrentUser())
- func DebugJSON(moduleName, name string, value any) {
- Logger.Debug(moduleName, zap.String(name, jsonString(value)))
- }
- func InfoJSON(moduleName, name string, value any) {
- Logger.Info(moduleName, zap.String(name, jsonString(value)))
- }
- func WarnJSON(moduleName, name string, value any) {
- Logger.Warn(moduleName, zap.String(name, jsonString(value)))
- }
- func ErrorJSON(moduleName, name string, value any) {
- Logger.Error(moduleName, zap.String(name, jsonString(value)))
- }
- func FatalJSON(moduleName, name string, value any) {
- Logger.Fatal(moduleName, zap.String(name, jsonString(value)))
- }
- func jsonString(v any) string {
- b, err := json.Marshal(v)
- if err != nil {
- Logger.Error("Logger", zap.String("json.Marshal error", err.Error()))
- }
- return string(b)
- }
|