yinbangzhong
2024-07-29 9f78e3b126b15a9b331c3a1a318da1ceea30114c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package logx
 
import (
    "go.uber.org/zap"
    "go.uber.org/zap/buffer"
    "go.uber.org/zap/zapcore"
    "gopkg.in/natefinch/lumberjack.v2"
    "os"
    "path"
    "strings"
)
 
type (
    LogConf struct {
        Path       string         // 日志路径
        Encoder    string         // 编码器选择
        LogLevel   *zapcore.Level // 日志级别
        LogFile    string         // 日志文件路径
        MaxSize    int            // 每个日志文件的最大大小(MB)
        MaxBackups int            // 保留的旧日志文件个数
        RotateDays int            // 日志文件的最大保留天数
    }
    logItem struct {
        FileName string
        Level    zap.LevelEnablerFunc
    }
    Encoder interface {
        Config() zapcore.Encoder
        WithKey(key string) Encoder
        WithField(key, val string) Encoder
        Debug(msg string)
        Debugf(format string, v ...interface{})
        Info(msg string)
        Infof(format string, v ...interface{})
        Warn(msg string)
        Warnf(format string, v ...interface{})
        Error(msg string)
        Errorf(format string, v ...interface{})
        Fatal(msg string)
        Fatalf(format string, v ...interface{})
    }
)
 
var (
    maxSize    = 200 // 每个日志文件最大尺寸200M
    maxBackups = 2   // 日志文件最多保存20个备份
    maxAge     = 5   // 保留最大天数
    logLevel   = zapcore.WarnLevel
    _logger    *zap.Logger
    _pool      = buffer.NewPool()
 
    ConsoleEncoder = "console" // 控制台输出
    JsonEncoder    = "json"    // json输出
)
 
// Init 初始化日志.
func Init(conf LogConf) {
    if conf.LogLevel == nil {
        conf.LogLevel = &logLevel
    }
    prefix, suffix := getFileSuffixPrefix(conf.Path)
 
    logPath := path.Join(prefix + suffix)
    items := []logItem{
        {
            FileName: logPath,
            Level: func(level zapcore.Level) bool {
                return level >= *conf.LogLevel
            },
        },
    }
 
    NewLogger(items, conf)
}
 
// NewLogger 日志.
func NewLogger(items []logItem, conf LogConf) {
    var (
        cfg   zapcore.Encoder
        cores []zapcore.Core
    )
    switch conf.Encoder {
    case JsonEncoder:
        cfg = NewJsonLog().Config()
    case ConsoleEncoder:
        cfg = NewConsoleLog().Config()
    default:
        cfg = NewConsoleLog().Config()
    }
 
    if conf.RotateDays == 0 {
        conf.RotateDays = maxAge
    }
    if conf.MaxBackups == 0 {
        conf.MaxBackups = maxBackups
    }
    if conf.MaxSize == 0 {
        conf.MaxSize = maxSize
    }
 
    for _, v := range items {
        hook := lumberjack.Logger{
            Filename:   v.FileName,
            MaxSize:    conf.MaxSize,    // 每个日志文件保存的最大尺寸 单位:M
            MaxBackups: conf.MaxBackups, // 日志文件最多保存多少个备份
            MaxAge:     conf.RotateDays, // 文件最多保存多少天
            Compress:   true,            // 是否压缩
            LocalTime:  true,            // 备份文件名本地/UTC时间
        }
        core := zapcore.NewCore(
            cfg, // 编码器配置;
            zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(&hook)), // 打印到控制台和文件
            v.Level, // 日志级别
        )
        cores = append(cores, core)
    }
 
    // 开启开发模式,堆栈跟踪
    caller := zap.AddCaller()
    // 开发模式
    development := zap.Development()
    // 二次封装
    skip := zap.AddCallerSkip(1)
    // 构造日志
    _logger = zap.New(zapcore.NewTee(cores...), caller, development, skip)
    return
}
 
// GetEncoder 获取自定义编码器.
func GetEncoder(conf LogConf) Encoder {
    switch conf.Encoder {
    case JsonEncoder:
        return NewJsonLog()
    case ConsoleEncoder:
        return NewConsoleLog()
    default:
        return NewConsoleLog()
    }
}
 
// GetLogger 获取日志记录器.
func GetLogger() *zap.Logger {
    return _logger
}
 
// getFileSuffixPrefix 文件路径切割
func getFileSuffixPrefix(fileName string) (prefix, suffix string) {
    paths, _ := path.Split(fileName)
    base := path.Base(fileName)
    suffix = path.Ext(fileName)
    prefix = strings.TrimSuffix(base, suffix)
    prefix = path.Join(paths, prefix)
    return
}
 
// getFilePath 自定义获取文件路径.
func getFilePath(ec zapcore.EntryCaller) string {
    if !ec.Defined {
        return "undefined"
    }
    buf := _pool.Get()
    buf.AppendString(ec.Function)
    buf.AppendByte(':')
    buf.AppendInt(int64(ec.Line))
    caller := buf.String()
    buf.Free()
    return caller
}