深入浅析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 相关文章推荐
一个轻量级的javascript库 pj介绍
Dec 19 Javascript
基于jQuery的为attr添加id title等效果的实现代码
Apr 20 Javascript
通过Javascript读取本地Excel文件内容的代码示例
Apr 08 Javascript
jQuery四种选择器使用及示例
Jun 05 Javascript
js中string和number类型互转换技巧(分享)
Nov 28 Javascript
原生JS实现简单放大镜效果
Feb 08 Javascript
JavaScript实现的浏览器下载文件的方法
Aug 09 Javascript
react中使用swiper的具体方法
May 15 Javascript
vue2.0$nextTick监听数据渲染完成之后的回调函数方法
Sep 11 Javascript
JS+CSS3实现的简易钟表效果示例
Apr 13 Javascript
vue实现路由不变的情况下,刷新页面操作示例
Feb 02 Javascript
uniapp开发打包多端应用完整方法指南
Dec 24 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数组中的重复值的实现代码
2011/07/17 PHP
mysql总结之explain
2012/02/27 PHP
PHP中常用的转义函数
2014/02/28 PHP
浅谈php函数serialize()与unserialize()的使用方法
2014/08/19 PHP
php实现图片添加描边字和马赛克的方法
2014/12/10 PHP
ThinkPHP框架结合Ajax实现用户名校验功能示例
2019/07/03 PHP
一组JS创建和操作表格的函数集合
2009/05/07 Javascript
解决jquery .ajax 在IE下卡死问题的解决方法
2009/10/26 Javascript
js 实现日期灵活格式化的小例子
2013/07/14 Javascript
JS 获取滚动条高度示例代码
2013/10/24 Javascript
几种设置表单元素中文本输入框不可编辑的方法总结
2013/11/25 Javascript
一个JS函数搞定网页标题(title)闪动效果
2014/05/13 Javascript
使用命令对象代替switch语句的写法示例
2015/02/28 Javascript
AngularJS equal比较对象实例详解
2016/09/14 Javascript
jQuery实现的仿百度,仿谷歌搜索下拉框效果示例
2016/12/30 Javascript
BootStrap与Select2使用小结
2017/02/17 Javascript
Vue传参一箩筐(页面、组件)
2019/04/04 Javascript
JavaScript Array对象基本方法详解
2019/09/03 Javascript
微信小程序点击按钮动态切换input的disabled禁用/启用状态功能
2020/03/07 Javascript
Python使用tablib生成excel文件的简单实现方法
2016/03/16 Python
Python MySQLdb 使用utf-8 编码插入中文数据问题
2018/03/13 Python
python opencv将图片转为灰度图的方法示例
2019/07/31 Python
Python第三方包之DingDingBot钉钉机器人
2020/04/09 Python
如何基于Python Matplotlib实现网格动画
2020/07/20 Python
Python利用命名空间解析XML文档
2020/08/10 Python
Shoes For Crews法国官网:美国领先的防滑鞋设计和制造商
2018/01/01 全球购物
eDreams葡萄牙:全球最大的在线旅行社之一
2019/04/15 全球购物
英国最好的温室之家:Greenhouses Direct
2019/07/13 全球购物
Etam俄罗斯:法国女士内衣和家居服网上商店
2019/10/30 全球购物
英国门销售网站:Green Tree Doors
2020/01/07 全球购物
优秀毕业生找工作自荐信
2014/06/23 职场文书
党委领导班子整改方案
2014/09/30 职场文书
质量保证书怎么写
2015/02/27 职场文书
小学六一儿童节活动开幕词
2016/03/04 职场文书
Go语言带缓冲的通道实现
2021/04/26 Golang
Python Pandas知识点之缺失值处理详解
2021/05/11 Python