go基于grpc构建微服务框架-结构化日志输出

go基于grpc构建微服务框架-结构化日志输出

大家好,又见面了,我是你们的朋友全栈君。

1.结构化日志的意义

1.1 日志格式化

日志主要用于跟踪服务的运行信息,作为后端攻城狮,一般都会有一种想法,平时的时候希望日志越少越好,出问题的时候又总是抱怨,怎么才tmd这点日志,还在关键的地方没打印.

因此,日志很重要,将日志进行格式化也很重要,日志格式化主要是为了方便后续进行分析.如通过将错误码格式化到日志中,我们可以对收集后的日志分析接口的调用健康状态,将接口耗时格式化后上报,可以监控延时高的操作,并查询出关联日志进行分析.

所以只要是格式化输出,很容易有很多应用.

1.2 日志库应该有的特性

  • 高性能

这里主要是两方面,每次操作的耗时,以及每次操作分配的内存,作为日志库,两个指标都应该要极低.

  • 日志等级过滤

能通过调节日志等级打印不同级别的日志.

  • 采样率

能够设置采样率,防止服务请求增加时输出的日志量剧增,从而影响服务性能.

  • 自动切分文件

自动按一定大小切分文件,定期归档,保存一定数量文件.

基于以上几点,选择uber开源的日志库 zap.

2.集成到grpc中

2.1 思路

grpc 定义了grpclog包,并定义了LoggerV2的接口,因此,只要通过zap实现LoggerV2的接口,并通过SetLoggerV2(l LoggerV2)接口将实现的对象设置到grpclog包中,那么grpc将使用zap进行日志输出,同时上层应用也可以使用grpclog进行业务日志打印.

2.2 实现

完整代码以及使用示例见 grpc-wrapper

type ZapLogger struct {
    logger *zap.Logger
}

//创建封装了zap的对象,该对象是对LoggerV2接口的实现
func NewZapLogger(logger *zap.Logger) *ZapLogger {
    return &ZapLogger{
        logger: logger,
    }
}
func (zl *ZapLogger) Info(args ...interface{}) {
    zl.logger.Sugar().Info(args...)
}

func (zl *ZapLogger) Infoln(args ...interface{}) {
    zl.logger.Sugar().Info(args...)
}
func (zl *ZapLogger) Infof(format string, args ...interface{}) {
    zl.logger.Sugar().Infof(format, args...)
}

func (zl *ZapLogger) Warning(args ...interface{}) {
    zl.logger.Sugar().Warn(args...)
}

func (zl *ZapLogger) Warningln(args ...interface{}) {
    zl.logger.Sugar().Warn(args...)
}

func (zl *ZapLogger) Warningf(format string, args ...interface{}) {
    zl.logger.Sugar().Warnf(format, args...)
}

func (zl *ZapLogger) Error(args ...interface{}) {
    zl.logger.Sugar().Error(args...)
}

func (zl *ZapLogger) Errorln(args ...interface{}) {
    zl.logger.Sugar().Error(args...)
}

func (zl *ZapLogger) Errorf(format string, args ...interface{}) {
    zl.logger.Sugar().Errorf(format, args...)
}

func (zl *ZapLogger) Fatal(args ...interface{}) {
    zl.logger.Sugar().Fatal(args...)
}

func (zl *ZapLogger) Fatalln(args ...interface{}) {
    zl.logger.Sugar().Fatal(args...)
}

// Fatalf logs to fatal level
func (zl *ZapLogger) Fatalf(format string, args ...interface{}) {
    zl.logger.Sugar().Fatalf(format, args...)
}

// V reports whether verbosity level l is at least the requested verbose level.
func (zl *ZapLogger) V(v int) bool {
    return false
}

3.最终效果

go基于grpc构建微服务框架-结构化日志输出

可以看到,日志以json格式输出,并显示了日志打印时的代码行数,同时当出现error时进行了调用栈的追踪.

参考

grpc
zap.
grpc-wrapper

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/107566.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • C#中什么是泛型

    C#中什么是泛型参考视频c#教程泛型集合与非泛型集合最大的区别在于,泛型集合,不需要进行装箱和拆箱的操作。如集合元素为值类型,通常泛型集合要优于非泛型集合,并优于从非泛型集合派生出来的类型,泛是广泛的意思,而型是数据类型。这里的泛型可以理解为应用广泛的数据类型。为了提高性能及维护类型安全,一般最好采用泛型集合。如果两个类的内容完全一样,只是处理的数据类型不同。那么,采用泛型是一个不错的选择。泛型类用于封装不是特定于具体数据类型的操作,通常用于集合。诸如从集合中添加和移除项这样的操作都以大体上相同的方式执行,与所存

  • 邮件群发怎么设置_qq邮箱邮件怎么群发

    邮件群发怎么设置_qq邮箱邮件怎么群发大家都说30岁的女人一枝花,但是我就狠狠的被家里人催婚了。老妈让我去参加一个相亲,虽然心里不想去,但是为了让老妈开心,还是去参加了这场相亲局。当相亲那天来临时,我进入了跟人约好的咖啡馆,见面时寒暄了几句,就进入了无声的沉默,后来我们聊天时提起了我们的职业,我说我是外企HR,他跟我说他是会展公司的市场部部员,然后我问他工作具体是干什么的,然后他跟我说他是具体用邮件来开发客户,介绍会展公司承包的展览这种工作。我说好厉害的样子,你们是不是也需要邮件群发啊?最近我的邮箱有限,不是特别好用,刚好想换一个邮箱,你平常使

    2022年10月30日
  • crontab每秒执行一次命令_crontab每天1点执行

    crontab每秒执行一次命令_crontab每天1点执行根据上图,在linux中crontab的最小执行单位是分钟,没法直接实现单位秒的运行,所以得通过其他方式来处理。思路:假如每15秒运行一次,那就运行一次后睡眠15秒,15秒后再睡眠10秒,依次类推。crontab-e*/1****/root/python.sh*/1****sleep15;/root/python.sh*/1****sleep30…

  • rownumber实现分页的方法

    rownumber实现分页的方法利用rownumer实现分页的两种常用方式:1)利用betweendeclare@pagesizeintset@pagesize=4declare@pageindexintset@pageindex=3 select *from(s

  • 我的学习历程

    我的学习历程@[TOC]不负青春,加油干!自我介绍及共勉大家好!我是一名准大三学生,进入编程的大门已经2年的时间,从大一的css与html再到大二的java,javaweb,数据结构与算法(想哭的有没有),mysql,javascript,vue.js,javaee。我从一个啥也不会的小白转变成一个啥都想尝试的大白其中有艰难(调试bug弄了一晚上)有失落(参加蓝桥杯没拿奖)有幸福(用程序给女朋友写了个生日祝福软件)有迷茫(不知道前面的路该怎么选择)。刚进入这个圈子是因为觉得弄计算机的人特别酷,觉得黑客是这个世

  • 浅聊:ES6模板字符串与一般字符串

    浅聊:ES6模板字符串与一般字符串一.模板字符串与一般字符串区别二.模板字符串的一些注意事项一.模板字符串与一般字符串区别1,认识模板字符串:’xiaozhang’ //一般字符串`xiaozhang` //模板字符串(用两个反引号裹着)constusername1=’xiaozhang’;constusername2=`xiaozhang`;console.log(username1,username2,usern..

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号