深入浅析golang zap 日志库使用(含文件切割、分级别存储和全局使用等)


Posted in Javascript onFebruary 19, 2020

日志处理经常有以下几个需求:

1、不同级别的日志输出到不同的日志文件中。

2、日志文件按照文件大小或日期进行切割存储,以避免单一日志文件过大。

3、日志使用简单方便,一次定义全局使用。

建议使用使用Uber-go的Zap Logger,大神李文周大博客已经说的非常明确了,请先参考李老师的博客:

https://www.liwenzhou.com/posts/Go/zap/

问题二和问题三需要补充描述:

一、日志按照级别分文件切割存储

1.1 首先实现两个判断日志等级的interface

infoLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
 return lvl >= zapcore.InfoLevel
})

errorLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
 return lvl >= zapcore.ErrorLevel
})

1.2 获取 info、error日志文件的io.Writer

infoWriter := getWriter("./logs/demo_info.log")
errorWriter := getWriter("./logs/demo_error.log")

文件名可拼接入系统时间

func getWriter(filename string) io.Writer {
 // 生成rotatelogs的Logger 实际生成的文件名 demo.log.YYmmddHH
 // demo.log是指向最新日志的链接
 // 保存7天内的日志,每1小时(整点)分割一次日志
 hook, err := rotatelogs.New(
 strings.Replace(filename, ".log", "", -1)+"-%Y%m%d%H.log", // 没有使用go风格反人类的format格式
 //rotatelogs.WithLinkName(filename),
 //rotatelogs.WithMaxAge(time.Hour*24*7),
 //rotatelogs.WithRotationTime(time.Hour),
 )

 if err != nil {
 panic(err)
 }
 return hook
}

1.3 最后创建具体的Logger

core := zapcore.NewTee(
 zapcore.NewCore(encoder, zapcore.AddSync(infoWriter), infoLevel),
 zapcore.NewCore(encoder, zapcore.AddSync(errorWriter), errorLevel),
)

1.4 创建logger

log := zap.New(core, zap.AddCaller()) 
errorLogger = log.Sugar()

二、日志定义全局使用

定义完一个logger 之后,我们希望整个项目可以拿来即用,不需要在每个文件里都进行初始化,我们使用go函数中的静态函数来实现。

2.1 定义一个logger包

深入浅析golang zap 日志库使用(含文件切割、分级别存储和全局使用等)

2.2 定义外部可直接访问的函数

注意函数首字母要大写

func Debug(args ...interface{}) {
 errorLogger.Debug(args...)
}
func Debugf(template string, args ...interface{}) {
 errorLogger.Debugf(template, args...)
}
func Info(args ...interface{}) {
 errorLogger.Info(args...)
}
func Infof(template string, args ...interface{}) {
 errorLogger.Infof(template, args...)
}
func Warn(args ...interface{}) {
 errorLogger.Warn(args...)
}
func Warnf(template string, args ...interface{}) {
 errorLogger.Warnf(template, args...)
}
func Error(args ...interface{}) {
 errorLogger.Error(args...)
}
func Errorf(template string, args ...interface{}) {
 errorLogger.Errorf(template, args...)
}
func DPanic(args ...interface{}) {
 errorLogger.DPanic(args...)
}
func DPanicf(template string, args ...interface{}) {
 errorLogger.DPanicf(template, args...)
}

2.3 在需要使用的地方直接引入logger 包就可以直接使用

logger.Infof("create token succ , token=%v", token)

三、源码

3.1 文件目录

深入浅析golang zap 日志库使用(含文件切割、分级别存储和全局使用等)

3.2 lgo.go 源码

package logger
import (
 rotatelogs "github.com/lestrrat-go/file-rotatelogs"
 "go.uber.org/zap"
 "go.uber.org/zap/zapcore"
 "io"
 "strings"
 "time"
)
var errorLogger *zap.SugaredLogger
func init(){
 // 设置一些基本日志格式 具体含义还比较好理解,直接看zap源码也不难懂
 encoder := zapcore.NewConsoleEncoder(zapcore.EncoderConfig{
 MessageKey: "msg",
 LevelKey: "level",
 EncodeLevel: zapcore.CapitalLevelEncoder,
 TimeKey: "ts",
 EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
  enc.AppendString(t.Format("2006-01-02 15:04:05"))
 },
 CallerKey: "file",
 EncodeCaller: zapcore.ShortCallerEncoder,
 EncodeDuration: func(d time.Duration, enc zapcore.PrimitiveArrayEncoder) {
  enc.AppendInt64(int64(d) / 1000000)
 },
 })
 // 实现两个判断日志等级的interface
 infoLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
 return lvl >= zapcore.InfoLevel
 })
 errorLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
 return lvl >= zapcore.ErrorLevel
 })
 // 获取 info、error日志文件的io.Writer 抽象 getWriter() 在下方实现
 infoWriter := getWriter("./logs/demo_info.log")
 errorWriter := getWriter("./logs/demo_error.log")
 // 最后创建具体的Logger
 core := zapcore.NewTee(
 zapcore.NewCore(encoder, zapcore.AddSync(infoWriter), infoLevel),
 zapcore.NewCore(encoder, zapcore.AddSync(errorWriter), errorLevel),
 )
 log := zap.New(core, zap.AddCaller()) // 需要传入 zap.AddCaller() 才会显示打日志点的文件名和行数, 有点小坑
 errorLogger = log.Sugar()
}
func getWriter(filename string) io.Writer {
 // 生成rotatelogs的Logger 实际生成的文件名 demo.log.YYmmddHH
 // demo.log是指向最新日志的链接
 // 保存7天内的日志,每1小时(整点)分割一次日志
 hook, err := rotatelogs.New(
 strings.Replace(filename, ".log", "", -1)+"-%Y%m%d%H.log", // 没有使用go风格反人类的format格式
 //rotatelogs.WithLinkName(filename),
 //rotatelogs.WithMaxAge(time.Hour*24*7),
 //rotatelogs.WithRotationTime(time.Hour),
 )
 if err != nil {
 panic(err)
 }
 return hook
}
func Debug(args ...interface{}) {
 errorLogger.Debug(args...)
}
func Debugf(template string, args ...interface{}) {
 errorLogger.Debugf(template, args...)
}
func Info(args ...interface{}) {
 errorLogger.Info(args...)
}
func Infof(template string, args ...interface{}) {
 errorLogger.Infof(template, args...)
}
func Warn(args ...interface{}) {
 errorLogger.Warn(args...)
}
func Warnf(template string, args ...interface{}) {
 errorLogger.Warnf(template, args...)
}
func Error(args ...interface{}) {
 errorLogger.Error(args...)
}
func Errorf(template string, args ...interface{}) {
 errorLogger.Errorf(template, args...)
}
func DPanic(args ...interface{}) {
 errorLogger.DPanic(args...)
}
func DPanicf(template string, args ...interface{}) {
 errorLogger.DPanicf(template, args...)
}
func Panic(args ...interface{}) {
 errorLogger.Panic(args...)
}
func Panicf(template string, args ...interface{}) {
 errorLogger.Panicf(template, args...)
}
func Fatal(args ...interface{}) {
 errorLogger.Fatal(args...)
}
func Fatalf(template string, args ...interface{}) {
 errorLogger.Fatalf(template, args...)
}

3.3 main 函数使用

import (
 "flag"
 "goAuth/logger"
 "goAuth/util"
 "os"
)

func main() {
 createAndCheckToken()
 logger.Infof("in main args:%v", os.Args)
 logger.Errorf("eerror %v", "error")
 flag.Parse()
 logger.Infof("env is %v", *env)
 config := util.InitConfig( "./config/" + *env + ".conf")
 ip := config["ip"]
 port := config["port"]
 envConfig := config["env"]
 logger.Infof("ip=%v, port=%v, env=%v", ip, port, envConfig)
}

总结

以上所述是小编给大家介绍的golang zap 日志库使用(含文件切割、分级别存储和全局使用等),希望对大家有所帮助,也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
对联广告js flash激活
Oct 19 Javascript
重载toString实现JS HashMap分析
Mar 13 Javascript
javascript作用域容易记错的两个地方分析
Jun 22 Javascript
javascript 利用Image对象实现的埋点(某处的点击数)统计
Dec 28 Javascript
JS保存和删除cookie操作 判断cookie是否存在
Nov 13 Javascript
用console.table()调试javascript
Sep 04 Javascript
jQuery双向列表选择器select版
Nov 01 Javascript
浅谈移动端之js touch事件 手势滑动事件
Nov 07 Javascript
微信小程序 this和that详解及简单实例
Feb 13 Javascript
微信小程序 下拉列表的实现实例代码
Mar 08 Javascript
react 应用多入口配置及实践总结
Oct 17 Javascript
微信小程序登录对接Django后端实现JWT方式验证登录详解
Jul 29 Javascript
vue中实现回车键登录功能
Feb 19 #Javascript
Vue中实现回车键切换焦点的方法
Feb 19 #Javascript
整理 node-sass 安装失败的原因及解决办法(小结)
Feb 19 #Javascript
Vue常用的全选/反选的示例代码
Feb 19 #Javascript
详解node和ES6的模块导出与导入
Feb 19 #Javascript
JS实现分页导航效果
Feb 19 #Javascript
vue随机验证码组件的封装实现
Feb 19 #Javascript
You might like
php 使用file_get_contents读取大文件的方法
2014/11/13 PHP
PHP实现使用DOM将XML数据存入数组的方法示例
2017/09/27 PHP
区分JS中的undefined,null,"",0和false
2007/03/08 Javascript
HTML代码中标签的全部属性 中文注释说明
2009/03/26 Javascript
js下用gb2312编码解码实现方法
2009/12/31 Javascript
jquery获取input的value问题说明
2010/08/19 Javascript
JavaScript实现多个重叠层点击切换效果的方法
2015/04/24 Javascript
jquery实现手机端单店铺购物车结算删除功能
2017/02/22 Javascript
js+canvas实现动态吃豆人效果
2017/03/22 Javascript
Angular @HostBinding()和@HostListener()用法
2018/03/05 Javascript
jQuery实现获取选中复选框的值实例详解
2018/06/28 jQuery
vue项目启动出现cannot GET /服务错误的解决方法
2020/04/26 Javascript
Python对象类型及其运算方法(详解)
2017/07/05 Python
Python实现压缩和解压缩ZIP文件的方法分析
2017/09/28 Python
Python3使用正则表达式爬取内涵段子示例
2018/04/22 Python
python基于递归解决背包问题详解
2019/07/03 Python
python性能测量工具cProfile使用解析
2019/09/26 Python
python 插入日期数据到Oracle实例
2020/03/02 Python
Python3实现打印任意宽度的菱形代码
2020/04/12 Python
Python通过len函数返回对象长度
2020/10/22 Python
python正则表达式re.match()匹配多个字符方法的实现
2021/01/27 Python
HTML5 本地存储实现购物车功能
2017/09/07 HTML / CSS
html5中为audio标签增加停止按钮动作实现方法
2013/01/04 HTML / CSS
HTML5 manifest离线缓存的示例代码
2018/08/08 HTML / CSS
JD Sports德国官网:英国领先的运动鞋和运动服饰零售商
2018/02/26 全球购物
法国春天百货官网:Printemps.com
2020/06/29 全球购物
Shell编程面试题
2012/05/30 面试题
中医药大学市场营销专业自荐信
2013/09/29 职场文书
电大自我鉴定
2013/10/27 职场文书
医药销售自我评价200字
2014/09/11 职场文书
兴趣班停课通知
2015/04/24 职场文书
导游词之介休绵山
2019/12/31 职场文书
详解gantt甘特图可拖拽、编辑(vue、react都可用 highcharts)
2021/11/27 Vue.js
叶县这家生产军用电台的兵工厂,人称“四机部”,走出一上将
2022/02/18 无线电
使用Ajax实现进度条的绘制
2022/04/07 Javascript
python数字图像处理之对比度与亮度调整示例
2022/06/28 Python