日志管理
推荐学习:
因为日志模式分开发调试和生产模式,所以需要根据配置文件生成相关得日志对象。
开发调试模式
// 判断程序当前所处的模式,调试模式直接返回一个便捷的zap日志管理器地址,所有的日志打印到控制台即可
//挂载钩子函数
if appDebug == true {
if logger, err := zap.NewDevelopment(zap.Hooks(entry)); err == nil {
return logger
} else {
log.Fatal("创建zap日志包失败,详情:" + err.Error())
}
}
复制代码
生产模式
这里生产模式采用的是定制logger方式,同时在生产模式日志就不应该打印到应用程序控制台中了,应该写入文件中。
第一步:Encoder:编码器(如何写入日志)。
encoderConfig := zap.NewProductionEncoderConfig()
var encoder zapcore.Encoder
switch variable.ConfigYml.GetString("Logs.TextFormat") {
case "console":
encoder = zapcore.NewConsoleEncoder(encoderConfig) // 普通模式
case "json":
encoder = zapcore.NewJSONEncoder(encoderConfig) // json格式
default:
encoder = zapcore.NewConsoleEncoder(encoderConfig) // 普通模式
}
复制代码
根据配置文件选择写入文件的方式。
第二步:WriterSyncer :指定日志将写到哪里去。
//写入文件位置
fileName := variable.BasePath + variable.ConfigYml.GetString("Logs.GoSkeletonLogName")
//配置相关信息(日志切割归档功能)
lumberJackLogger := &lumberjack.Logger{
Filename: fileName, //日志文件的位置
MaxSize: variable.ConfigYml.GetInt("Logs.MaxSize"), //在进行切割之前,日志文件的最大大小(以MB为单位)
MaxBackups: variable.ConfigYml.GetInt("Logs.MaxBackups"), //保留旧文件的最大个数
MaxAge: variable.ConfigYml.GetInt("Logs.MaxAge"), //保留旧文件的最大天数
Compress: variable.ConfigYml.GetBool("Logs.Compress"), //是否压缩/归档旧文件
}
//写入器
writer := zapcore.AddSync(lumberJackLogger)
复制代码
第三步:Log Level:哪种级别的日志将被写入。
//debug级别支持后续调用的所有函数写日志,如果是 fatal 高级别,则级别>=fatal 才可以写日志
//选择zap日志级别
// DebugLevel logs are typically voluminous, and are usually disabled in
// production.
DebugLevel = zapcore.DebugLevel
// InfoLevel is the default logging priority.
InfoLevel = zapcore.InfoLevel
// WarnLevel logs are more important than Info, but don't need individual
// human review.
WarnLevel = zapcore.WarnLevel
// ErrorLevel logs are high-priority. If an application is running smoothly,
// it shouldn't generate any error-level logs.
ErrorLevel = zapcore.ErrorLevel
// DPanicLevel logs are particularly important errors. In development the
// logger panics after writing the message.
DPanicLevel = zapcore.DPanicLevel
// PanicLevel logs a message, then panics.
PanicLevel = zapcore.PanicLevel
// FatalLevel logs a message, then calls os.Exit(1).
FatalLevel = zapcore.FatalLevel
复制代码
第四步:添加其他功能(时间等)(可选)
//获取时间格式化的级别
timePrecision := variable.ConfigYml.GetString("Logs.TimePrecision")
//对时间进行格式化
var recordTimeFormat string
switch timePrecision {
case "second":
recordTimeFormat = "2006-01-02 15:04:05"
case "millisecond":
recordTimeFormat = "2006-01-02 15:04:05.000"
default:
recordTimeFormat = "2006-01-02 15:04:05"
}
//修改时间编码器
encoderConfig.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(t.Format(recordTimeFormat))
}
//在日志文件中使用大写字母记录日志级别
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
复制代码
最后一步:创建zap日志对象
// 开始初始化zap日志核心参数,
//参数一:编码器
//参数二:写入器
//参数三:参数级别,debug级别支持后续调用的所有函数写日志,如果是 fatal 高级别,则级别>=fatal 才可以写日志
zapCore := zapcore.NewCore(encoder, writer, zap.InfoLevel)
//挂载钩子函数
return zap.New(zapCore, zap.AddCaller(), zap.Hooks(entry))
复制代码
钩子
日志可以对接阿里云日志管理面板,ELK等管理,所以需要获取所有的日志信息,然后通过操作推送上去。
// GoSkeleton 系统运行日志钩子函数
// 1.单条日志就是一个结构体格式,本函数拦截每一条日志,您可以进行后续处理,例如:推送到阿里云日志管理面板、ElasticSearch 日志库等
func ZapLogHandler(entry zapcore.Entry) error {
// 参数 entry 介绍
// entry 参数就是单条日志结构体,主要包括字段如下:
//Level 日志等级
//Time 当前时间
//LoggerName 日志名称
//Message 日志内容
//Caller 各个文件调用路径
//Stack 代码调用栈
//这里启动一个协程,hook丝毫不会影响程序性能,
go func(paramEntry zapcore.Entry) {
//fmt.Println(" GoSkeleton hook ....,你可以在这里继续处理系统日志....")
//fmt.Printf("%#+v\n", paramEntry)
}(entry)
return nil
}
复制代码
初始化
// 5.初始化全局日志句柄,并载入日志钩子处理函数
variable.ZapLog = zap_factory.CreateZapFactory(sys_log_hook.ZapLogHandler)
复制代码
使用
用法一:
//常用方式。
variable.ZapLog.Info("基本的运行提示类信息")
variable.ZapLog.Warn("UserCreate接口参数非法警告,相关参数:",zap.String("userName","demo_name"),zap.Int("userAge",18))
variable.ZapLog.Panic("UserDestory接口参数异常,相关参数:",zap.String("userName","demo_name"),zap.String("password","pass123456")
variable.ZapLog.Error("UserDestory接口参数错误,相关参数:",zap.Error(error))
variable.ZapLog.Fatal("Mysql初始化参数错误,退出运行。相关参数:",zap.String("name","root"), zap.Int("端口",3306))
复制代码
用法二:
# 第一种的函数后面全部添加了一个 w ,相关的函数功能和第一种一模一样
variable.ZapLog.Sugar().Infow("基本的运行提示类信息",zap.String("name","root"))
# 格式化参数,第一种用法中的函数后面添加了一个 f
variable.ZapLog.Sugar().Infof("参数 userId %d\n",2020)
variable.ZapLog.Sugar().Errorw("程序发生错误",zap.Error(error))
variable.ZapLog.Sugar().Errorf("参数非法,程序出错,userId %d\n",2020)
Warn 、 Panic 、Fatal用法类似
复制代码
温馨提示
gin的日志=nginx日志 gorm的日志=业务日志
分清楚每个日志的区别。不要把日志全部的混在一起。
在这里日志是这样管理的
- 当处于调试模式,gin的日志会直接打出到控制台,gorm的日志会写入全局日志
GoSkeletonLogName
- 当处于开发模式,gin的日志会新建立一个文件
GinLogName
,写入到这里,然后其他日志写入全局日志中
总结:
zap
是用来全局日志管理gorm日志。
根据模式是否开启gin日志。
//如果你用nginx做了代理,可以获取相关日志,不用gin去记录日志,开启生产模式
gin.SetMode(gin.ReleaseMode)
复制代码