Skip to content

Commit 70e0103

Browse files
authored
Create zap_log.go
1 parent cfa54ba commit 70e0103

File tree

1 file changed

+183
-0
lines changed

1 file changed

+183
-0
lines changed

golang/zap_log.go

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
package logger
2+
3+
import (
4+
"context"
5+
"os"
6+
"path/filepath"
7+
"time"
8+
9+
"github.com/natefinch/lumberjack"
10+
"go.uber.org/zap"
11+
"go.uber.org/zap/zapcore"
12+
"google.golang.org/grpc"
13+
"google.golang.org/grpc/connectivity"
14+
)
15+
16+
const DefaultLogPath = "/var/agent/" // 默认输出日志文件路径
17+
const DefaultLogName = "default.log"
18+
19+
type LogConfigs struct {
20+
LogLevel string // 日志打印级别 debug info warning error
21+
LogFormat string // 输出日志格式 logfmt, json
22+
LogPath string // 输出日志文件路径
23+
LogFileName string // 输出日志文件名称
24+
LogFileMaxSize int // 【日志分割】单个日志文件最多存储量 单位(mb)
25+
LogFileMaxBackups int // 【日志分割】日志备份文件最多数量
26+
LogMaxAge int // 日志保留时间,单位: 天 (day)
27+
LogCompress bool // 是否压缩日志
28+
LogStdout bool // 是否输出到控制台
29+
}
30+
31+
// InitLogger 初始化 log
32+
func InitLogger(conf LogConfigs) error {
33+
logLevel := map[string]zapcore.Level{
34+
"debug": zapcore.DebugLevel,
35+
"info": zapcore.InfoLevel,
36+
"warn": zapcore.WarnLevel,
37+
"error": zapcore.ErrorLevel,
38+
}
39+
40+
// init log channel
41+
logCh = make(chan []byte, 2048)
42+
43+
writeSyncer, err := getLogWriter(conf) // 日志文件配置 文件位置和切割
44+
if err != nil {
45+
return err
46+
}
47+
encoder := getEncoder(conf) // 获取日志输出编码
48+
level, ok := logLevel[conf.LogLevel] // 日志打印级别
49+
if !ok {
50+
level = logLevel["info"]
51+
}
52+
core := zapcore.NewCore(encoder, writeSyncer, level)
53+
logger := zap.New(core, zap.AddCaller()) // zap.Addcaller() 输出日志打印文件和行数如: logger/logger_test.go:33
54+
// 1. zap.ReplaceGlobals 函数将当前初始化的 logger 替换到全局的 logger,
55+
// 2. 使用 logger 的时候 直接通过 zap.S().Debugf("xxx") or zap.L().Debug("xxx")
56+
// 3. 使用 zap.S() 和 zap.L() 提供全局锁,保证一个全局的安全访问logger的方式
57+
zap.ReplaceGlobals(logger)
58+
//zap.L().Debug("")
59+
//zap.S().Debugf("")
60+
return nil
61+
}
62+
63+
// getEncoder 编码器(如何写入日志)
64+
func getEncoder(conf LogConfigs) zapcore.Encoder {
65+
66+
encoderConfig := zap.NewProductionEncoderConfig()
67+
68+
customTimeEncoder := func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
69+
enc.AppendString(t.Format("2006-01-02 15:04:05.000"))
70+
}
71+
encoderConfig.EncodeTime = customTimeEncoder // log 时间格式 例如: 2021-09-11t20:05:54.852+0800
72+
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder // 输出level序列化为全大写字符串,如 INFO DEBUG ERROR
73+
//encoderConfig.EncodeCaller = zapcore.FullCallerEncoder
74+
//encoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
75+
if conf.LogFormat == "json" {
76+
return zapcore.NewJSONEncoder(encoderConfig) // 以json格式写入
77+
}
78+
return zapcore.NewConsoleEncoder(encoderConfig) // 以logfmt格式写入
79+
}
80+
81+
// getLogWriter 获取日志输出方式 日志文件 控制台
82+
func getLogWriter(conf LogConfigs) (zapcore.WriteSyncer, error) {
83+
84+
// 判断日志路径是否存在,如果不存在就创建
85+
if exist := IsExist(conf.LogPath); !exist {
86+
if conf.LogPath == "" {
87+
conf.LogPath = DefaultLogPath
88+
}
89+
if conf.LogFileName == "" {
90+
conf.LogFileName = DefaultLogName
91+
}
92+
if err := os.MkdirAll(conf.LogPath, os.ModePerm); err != nil {
93+
conf.LogPath = DefaultLogPath
94+
if err := os.MkdirAll(conf.LogPath, os.ModePerm); err != nil {
95+
return nil, err
96+
}
97+
}
98+
}
99+
100+
// 日志文件 与 日志切割 配置
101+
lumberJackLogger := &lumberjack.Logger{
102+
Filename: filepath.Join(conf.LogPath, conf.LogFileName), // 日志文件路径
103+
MaxSize: conf.LogFileMaxSize, // 单个日志文件最大多少 mb
104+
MaxBackups: conf.LogFileMaxBackups, // 日志备份数量
105+
MaxAge: conf.LogMaxAge, // 日志最长保留时间
106+
Compress: conf.LogCompress, // 是否压缩日志
107+
}
108+
109+
// 日志同时输出到控制台、日志文件和grpc log中
110+
var writeSyncers []zapcore.WriteSyncer
111+
writeSyncers = append(writeSyncers, zapcore.AddSync(os.Stdout))
112+
writeSyncers = append(writeSyncers, zapcore.AddSync(lumberJackLogger))
113+
114+
grpcWrite := zapcore.AddSync(&GrpcLogChan{})
115+
writeSyncers = append(writeSyncers, grpcWrite)
116+
return zapcore.NewMultiWriteSyncer(writeSyncers...), nil
117+
118+
// if conf.LogStdout {
119+
// // 日志同时输出到控制台和日志文件中
120+
// return zapcore.NewMultiWriteSyncer(zapcore.AddSync(lumberJackLogger), zapcore.AddSync(os.Stdout)), nil
121+
// } else {
122+
// // 日志只输出到日志文件
123+
// return zapcore.AddSync(lumberJackLogger), nil
124+
// }
125+
}
126+
127+
// IsExist 判断文件或者目录是否存在
128+
func IsExist(path string) bool {
129+
_, err := os.Stat(path)
130+
return err == nil || os.IsExist(err)
131+
}
132+
133+
type GrpcLogChan struct {
134+
}
135+
136+
var logCh chan []byte
137+
138+
func (w *GrpcLogChan) Write(p []byte) (n int, err error) {
139+
d := make([]byte, len(p))
140+
copy(d, p)
141+
select {
142+
case logCh <- d:
143+
default:
144+
}
145+
146+
return
147+
}
148+
149+
func (w *GrpcLogChan) Sync() error {
150+
return nil
151+
}
152+
153+
func SendLogToServerTask(ctx context.Context, grpcConn *grpc.ClientConn) error {
154+
// log server client
155+
//client := pb.NewServicesClient(grpcConn)
156+
157+
for {
158+
select {
159+
case <-ctx.Done():
160+
zap.S().Warn("send log to server task ctx done, Bye...")
161+
return nil
162+
case v := <-logCh:
163+
/*
164+
if grpcConn.GetState() == connectivity.Ready {
165+
msgHdr := pb.ReqHeader{
166+
Time: common.GetCurrUnixTimestamp(),
167+
HostId: common.HostAgent.HostId,
168+
AgentId: common.HostAgent.AgentId,
169+
AgentVersion: common.HostAgent.AgentVersion,
170+
AgentToken: common.HostAgent.AgentToken,
171+
}
172+
msg := pb.ReportLogReq{
173+
ReqHdr: &msgHdr,
174+
LogData: string(v),
175+
}
176+
client.ReportLog(ctx, &msg)
177+
}
178+
*/
179+
}
180+
}
181+
return nil
182+
183+
}

0 commit comments

Comments
 (0)