深入浅析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下查找父节点的简单方法
Aug 13 Javascript
window.navigate 与 window.location.href 的使用区别介绍
Sep 21 Javascript
javascript中的遍历for in 以及with的用法
Dec 22 Javascript
jquery实现的美女拼图游戏实例
May 04 Javascript
JavaScript数组各种常见用法实例分析
Aug 04 Javascript
浅析js中substring和substr的方法
Nov 09 Javascript
浅谈js的异步执行
Oct 18 Javascript
微信小程序之picker日期和时间选择器
Feb 09 Javascript
浅谈js中用$(#ID)来作为选择器的问题(id重复的时候)
Feb 14 Javascript
仿ElementUI实现一个Form表单的实现代码
Apr 23 Javascript
Vue.js计算机属性computed和methods方法详解
Oct 12 Javascript
在antd Form表单中select设置初始值操作
Nov 02 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
模拟OICQ的实现思路和核心程序(二)
2006/10/09 PHP
php利用cookie实现访问次数统计代码
2011/05/19 PHP
PHP获取时间排除周六、周日的两个方法
2014/06/30 PHP
jQuery最佳实践完整篇
2011/08/20 Javascript
js原型链原理看图说明
2012/07/07 Javascript
Window.Open如何在同一个标签页打开
2014/06/20 Javascript
当前流行的JavaScript代码风格指南
2014/09/10 Javascript
JavaScript事件处理的方式(三种)
2016/04/26 Javascript
一个非常好用的文字滚动的案例,鼠标悬浮可暂停[两种方案任选]
2016/12/01 Javascript
解决AngualrJS页面刷新导致异常显示问题
2017/04/20 Javascript
Angular获取手机验证码实现移动端登录注册功能
2017/05/17 Javascript
easyui简介_动力节点Java学院整理
2017/07/14 Javascript
Angularjs的$http异步删除数据详解及实例
2017/07/27 Javascript
vue移动端路由切换实例分析
2018/05/14 Javascript
小程序日历控件使用方法详解
2018/12/29 Javascript
详解vue中this.$emit()的返回值是什么
2019/04/07 Javascript
微信小程序如何修改本地缓存key中单个数据的详解
2019/04/26 Javascript
详解Vue 如何监听Array的变化
2019/06/06 Javascript
vue父子组件的通信方法(实例详解)
2019/11/10 Javascript
JavaScript正则表达式验证登录实例
2020/03/18 Javascript
vscode 配置vue+vetur+eslint+prettier自动格式化功能
2020/03/23 Javascript
用Python编写一个国际象棋AI程序
2014/11/28 Python
windows及linux环境下永久修改pip镜像源的方法
2016/11/28 Python
浅谈Pytorch中的自动求导函数backward()所需参数的含义
2020/02/29 Python
后端开发使用pycharm的技巧(推荐)
2020/03/27 Python
解决python pandas读取excel中多个不同sheet表格存在的问题
2020/07/14 Python
CSS3 清除浮动的方法示例
2018/06/01 HTML / CSS
推荐10个HTML5响应式框架
2016/02/25 HTML / CSS
HTML5中原生的右键菜单创建方法
2016/06/28 HTML / CSS
6PM官网:折扣鞋、服装及配饰
2018/08/03 全球购物
美国户外运动商店:Sun & Ski
2018/08/23 全球购物
将"引用"作为函数返回值类型的格式、好处和需要遵守的规则
2016/02/09 面试题
护理自荐信范文
2013/10/05 职场文书
说谎欺骗人检讨书300字
2014/11/18 职场文书
goland 恢复已更改文件的操作
2021/04/28 Golang
聊聊Lombok中的@Builder注解使用教程
2021/11/17 Java/Android