fix
zhangqian
2023-08-27 8dfb8feb32bb5e4e460e23dcde42612a26fa2bcb
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
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 (
    Conf struct {
        Path    string // 日志路径
        Encoder string // 编码器选择
    }
    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 = 20  // 日志文件最多保存20个备份
    maxAge     = 30  // 保留最大天数
    _logger    *zap.Logger
    _pool      = buffer.NewPool()
    c          Conf
 
    ConsoleEncoder = "console" // 控制台输出
    JsonEncoder    = "json"    // json输出
)
 
// Init 初始化日志.
func Init(conf Conf) {
    c = conf
    prefix, suffix := getFileSuffixPrefix(c.Path)
 
    infoPath := path.Join(prefix + ".info" + suffix)
    errPath := path.Join(prefix + ".err" + suffix)
    items := []logItem{
        {
            FileName: infoPath,
            Level: func(level zapcore.Level) bool {
                return level <= zap.InfoLevel
            },
        },
        {
            FileName: errPath,
            Level: func(level zapcore.Level) bool {
                return level > zap.InfoLevel
            },
        },
    }
 
    NewLogger(items)
}
 
// NewLogger 日志.
func NewLogger(items []logItem) {
    var (
        cfg   zapcore.Encoder
        cores []zapcore.Core
    )
    switch c.Encoder {
    case JsonEncoder:
        cfg = NewJsonLog().Config()
    case ConsoleEncoder:
        cfg = NewConsoleLog().Config()
    default:
        cfg = NewConsoleLog().Config()
    }
 
    for _, v := range items {
        hook := lumberjack.Logger{
            Filename:   v.FileName,
            MaxSize:    maxSize,    // 每个日志文件保存的最大尺寸 单位:M
            MaxBackups: maxBackups, // 日志文件最多保存多少个备份
            MaxAge:     maxAge,     // 文件最多保存多少天
            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() Encoder {
    switch c.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
}