Go语言微服务框架 - 3.日志库的选型与引入

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 衡量日志库有多个指标,我们今天重点关注两点:简单易用 与 高性能。简单易用是一个日志库能被广泛使用的必要条件,而高性能则是企业级的日志库非常重要的衡量点,也能在源码层面对我们有一定的启发。

日志是一个框架的重要组成部分,那今天我们一起来看看这部分。

衡量日志库有多个指标,我们今天重点关注两点:简单易用高性能。简单易用是一个日志库能被广泛使用的必要条件,而高性能则是企业级的日志库非常重要的衡量点,也能在源码层面对我们有一定的启发。

v0.3.0:日志库的选型与引入

项目链接 https://github.com/Junedayday/micro_web_service/tree/v0.3.0

目标

选择一个开源的日志组件引入,支持常规的日志打印。

关键技术点

  1. 三款开源日志库的横向对比
  2. zap日志库的关键实现
  3. 关于日志参数的解析

目录构造

--- micro_web_service            项目目录
    |-- gen                            从idl文件夹中生成的文件,不可手动修改
       |-- idl                             对应idl文件夹
          |-- demo                             对应idl/demo服务
             |-- demo.pb.go                        demo.proto的基础结构
             |-- demo.pb.gw.go                     demo.proto的HTTP接口,对应gRPC-Gateway
             |-- demo_grpc.pb.go                   demo.proto的gRPC接口代码
    |-- idl                            原始的idl定义
       |-- demo                            业务package定义
          |-- demo.proto                       protobuffer的原始定义
    |-- internal                       项目的内部代码,不对外暴露
       |-- server                          服务器的实现
          |-- demo.go                          server中对demo这个服务的接口实现
          |-- server.go                        server的定义,须实现对应服务的方法
       |-- config                          配置相关的文件夹
          |-- viper.go                         viper的相关加载逻辑
     |-- zlog                            新增:封装日志的文件夹
        |-- zap.go                           新增:zap封装的代码实现
    |-- buf.gen.yaml                   buf生成代码的定义
    |-- buf.yaml                       buf工具安装所需的工具
    |-- gen.sh                         buf生成的shell脚本
    |-- go.mod                         Go Module文件
    |-- main.go                        项目启动的main函数

1.三款开源日志库的横向对比

如果用一次词语分别进行概括三者的特性,我分别会用:glog - 代码极简,logrus - 功能全面, zap - 高性能。经过反复思考,这个框架会选择zap库作为日志引擎的基本组件,主要考量如下:

  1. 高性能 - 性能是一个日志库很重要的属性,它往往由前期的设计决定,很难通过后面的优化大幅度提高,所以zap的高性能很难被替代;
  2. 方便封装 - zap设计简单,容易进行二次封装(glog更简洁,相应地就需要更多的封装代码)
  3. 大厂背书 - zap库被很多大公司引用,作为内部的日志库的底层,再二次开发
  4. 源码学习 - zap库对性能追求极高,可以作为高性能Go语言代码的分析样例

2.zap日志库的关键实现

最简化的调用

zap日志库的调用很简单,只需要两行代码就能实现初始化:

logger, _ := zap.NewProduction()
defer logger.Sync()

但这样的zap代码存在两个明显弊端:

  • 默认输出到控制台上
  • 无法保存到指定目录的文件

核心的日志文件实现

我们增加了一定的特性,代码如下:

var (
    // Logger为zap提供的原始日志,但使用起来比较烦,有强类型约束
    logger *zap.Logger
    // SugaredLogger为zap提供的一个通用性更好的日志组件,作为本项目的核心日志组件
    Sugar *zap.SugaredLogger
)

func Init(logPath string) {
   
    // 日志暂时只开放一个配置 - 配置文件路径,有需要可以后续开放
    hook := lumberjack.Logger{
   
        Filename: logPath,
    }
    w := zapcore.AddSync(&hook)

    encoderConfig := zap.NewProductionEncoderConfig()
    encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder

    core := zapcore.NewCore(
        zapcore.NewConsoleEncoder(encoderConfig),
        w,
        zap.InfoLevel,
    )

    logger = zap.New(core, zap.AddCaller())
    Sugar = logger.Sugar()
    return
}

// 命名和原生的Zap Log尽量一致,方便理解
func Sync() {
   
    logger.Sync()
}

那我们是如何解决上面两个问题的呢?

  1. 利用go.uber.org/zap/zapcore中的开放配置
  2. 借用了github.com/natefinch/lumberjack这个常用的日志切分库,也顺带实现了日志路径的支持

main函数的调用

var logFilePath = flag.String("l", "log/service.log", "log file path")
flag.Parse()

zlog.Init(*logFilePath)
defer zlog.Sync()

至此,我们的日志功能已经基本打通。

3.关于日志参数的解析

日志参数常见的方式分2种,一个是来自flag的解析,另一个是来自配置文件。

随着我们功能的拓展,日志库肯定会支持越来越复杂的场景。那这个时候用flag解析的扩展性就会很差,所以,我更推荐在微服务的框架中,用配置文件的方式去加载日志的相关配置。但这种方式会带来一个常见的现象:

程序代码的实现为:先加载配置文件,后加载日志,导致配置文件出错时,无法通过日志来排查,需要用控制台或者进程管理工具协助定位问题。

后续,随着框架的迭代,我会开放出更多的日志参数,目前只放出了一个日志路径的参数作为示例。

后续的两点核心需求

至此,我们添加的代码量并不多,也算成功地实现了一个日志打印的功能。但在实际的工程中,日志模块还需要实现两个比较大的功能:

  1. 支持Go程序Panic/Error Wrapping风格的多行打印与采集
  2. 支持分布式TraceId的打印,用来排查微服务调用链路

这两块的内容会结合具体的相关相关技术,会在后续专题中专门分享,请大家重点关注。

总结

zap库的代码是一个很棒的实现,我会在接下来的Go语言技巧系列中详细分析,欢迎大家进行关注。

至此,我们的框架逐渐成型,接下来我将对GORM做一个简单的讲解,引入到框架中。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
16天前
|
存储 监控 算法
员工上网行为监控中的Go语言算法:布隆过滤器的应用
在信息化高速发展的时代,企业上网行为监管至关重要。布隆过滤器作为一种高效、节省空间的概率性数据结构,适用于大规模URL查询与匹配,是实现精准上网行为管理的理想选择。本文探讨了布隆过滤器的原理及其优缺点,并展示了如何使用Go语言实现该算法,以提升企业网络管理效率和安全性。尽管存在误报等局限性,但合理配置下,布隆过滤器为企业提供了经济有效的解决方案。
60 8
员工上网行为监控中的Go语言算法:布隆过滤器的应用
|
1月前
|
Go 开发工具
百炼-千问模型通过openai接口构建assistant 等 go语言
由于阿里百炼平台通义千问大模型没有完善的go语言兼容openapi示例,并且官方答复assistant是不兼容openapi sdk的。 实际使用中发现是能够支持的,所以自己写了一个demo test示例,给大家做一个参考。
|
1月前
|
存储 Go 索引
go语言中的数组(Array)
go语言中的数组(Array)
109 67
|
1天前
|
监控 安全 算法
深度剖析核心科技:Go 语言赋能局域网管理监控软件进阶之旅
在局域网管理监控中,跳表作为一种高效的数据结构,能显著提升流量索引和查询效率。基于Go语言的跳表实现,通过随机化索引层生成、插入和搜索功能,在高并发场景下展现卓越性能。跳表将查询时间复杂度优化至O(log n),助力实时监控异常流量,保障网络安全与稳定。示例代码展示了其在实际应用中的精妙之处。
24 9
|
11天前
|
算法 安全 Go
Go 语言中实现 RSA 加解密、签名验证算法
随着互联网的发展,安全需求日益增长。非对称加密算法RSA成为密码学中的重要代表。本文介绍如何使用Go语言和[forgoer/openssl](https://github.com/forgoer/openssl)库简化RSA加解密操作,包括秘钥生成、加解密及签名验证。该库还支持AES、DES等常用算法,安装简便,代码示例清晰易懂。
46 12
|
14天前
|
监控 算法 安全
解锁企业计算机监控的关键:基于 Go 语言的精准洞察算法
企业计算机监控在数字化浪潮下至关重要,旨在保障信息资产安全与高效运营。利用Go语言的并发编程和系统交互能力,通过进程监控、网络行为分析及应用程序使用记录等手段,实时掌握计算机运行状态。具体实现包括获取进程信息、解析网络数据包、记录应用使用时长等,确保企业信息安全合规,提升工作效率。本文转载自:[VIPShare](https://www.vipshare.com)。
22 0
|
28天前
|
Go 数据安全/隐私保护 UED
优化Go语言中的网络连接:设置代理超时参数
优化Go语言中的网络连接:设置代理超时参数
|
2月前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
558 31
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
29天前
|
监控 安全 Apache
什么是Apache日志?为什么Apache日志分析很重要?
Apache是全球广泛使用的Web服务器软件,支持超过30%的活跃网站。它通过接收和处理HTTP请求,与后端服务器通信,返回响应并记录日志,确保网页请求的快速准确处理。Apache日志分为访问日志和错误日志,对提升用户体验、保障安全及优化性能至关重要。EventLog Analyzer等工具可有效管理和分析这些日志,增强Web服务的安全性和可靠性。
|
3月前
|
XML JSON Java
Logback 与 log4j2 性能对比:谁才是日志框架的性能王者?
【10月更文挑战第5天】在Java开发中,日志框架是不可或缺的工具,它们帮助我们记录系统运行时的信息、警告和错误,对于开发人员来说至关重要。在众多日志框架中,Logback和log4j2以其卓越的性能和丰富的功能脱颖而出,成为开发者们的首选。本文将深入探讨Logback与log4j2在性能方面的对比,通过详细的分析和实例,帮助大家理解两者之间的性能差异,以便在实际项目中做出更明智的选择。
383 3