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

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

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

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

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做一个简单的讲解,引入到框架中。

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
目录
相关文章
|
2月前
|
存储 监控 算法
防止员工泄密软件中文件访问日志管理的 Go 语言 B + 树算法
B+树凭借高效范围查询与稳定插入删除性能,为防止员工泄密软件提供高响应、可追溯的日志管理方案,显著提升海量文件操作日志的存储与检索效率。
120 2
|
8月前
|
JavaScript 前端开发 Java
通义灵码 Rules 库合集来了,覆盖Java、TypeScript、Python、Go、JavaScript 等
通义灵码新上的外挂 Project Rules 获得了开发者的一致好评:最小成本适配我的开发风格、相当把团队经验沉淀下来,是个很好功能……
1507 103
|
5月前
|
人工智能 测试技术 Go
Go 语言的主流框架
本文全面解析了 Go 语言主流技术生态,涵盖 Web 框架、微服务、数据库工具、测试与部署等多个领域。重点介绍了 Gin、Echo、Beego 等高性能框架,以及 gRPC-Go、Go-Micro 等微服务组件。同时分析了 GORM、Ent 等 ORM 工具与测试部署方案,并结合场景提供选型建议,助力开发者构建高效稳定的 Go 应用。
1501 0
|
3月前
|
消息中间件 缓存 NoSQL
Redis各类数据结构详细介绍及其在Go语言Gin框架下实践应用
这只是利用Go语言和Gin框架与Redis交互最基础部分展示;根据具体业务需求可能需要更复杂查询、事务处理或订阅发布功能实现更多高级特性应用场景。
312 86
|
2月前
|
JavaScript 前端开发 Java
【GoWails】Go做桌面应用开发?本篇文章带你上手Wails框架!一步步带你玩明白前后端双端的数据绑定!
wails是一个可以让你使用Go和Web技术编写桌面应用的项目 可以将它看作Go的快并且轻量级的Electron替代品。可以使用Go的功能,并结合现代化UI完成桌面应用程序的开发
630 4
|
2月前
|
开发框架 前端开发 Go
【GoGin】(0)基于Go的WEB开发框架,GO Gin是什么?怎么启动?本文给你答案
Gin:Go语言编写的Web框架,以更好的性能实现类似Martini框架的APInet/http、Beego:开源的高性能Go语言Web框架、Iris:最快的Go语言Web框架,完备的MVC支持。
400 1
|
8月前
|
人工智能 安全 Java
智慧工地源码,Java语言开发,微服务架构,支持分布式和集群部署,多端覆盖
智慧工地是“互联网+建筑工地”的创新模式,基于物联网、移动互联网、BIM、大数据、人工智能等技术,实现对施工现场人员、设备、材料、安全等环节的智能化管理。其解决方案涵盖数据大屏、移动APP和PC管理端,采用高性能Java微服务架构,支持分布式与集群部署,结合Redis、消息队列等技术确保系统稳定高效。通过大数据驱动决策、物联网实时监测预警及AI智能视频监控,消除数据孤岛,提升项目可控性与安全性。智慧工地提供专家级远程管理服务,助力施工质量和安全管理升级,同时依托可扩展平台、多端应用和丰富设备接口,满足多样化需求,推动建筑行业数字化转型。
310 5
|
6月前
|
开发框架 JSON 中间件
Go语言Web开发框架实践:路由、中间件、参数校验
Gin框架以其极简风格、强大路由管理、灵活中间件机制及参数绑定校验系统著称。本文详解其核心功能:1) 路由管理,支持分组与路径参数;2) 中间件机制,实现全局与局部控制;3) 参数绑定,涵盖多种来源;4) 结构体绑定与字段校验,确保数据合法性;5) 自定义校验器扩展功能;6) 统一错误处理提升用户体验。Gin以清晰模块化、流程可控及自动化校验等优势,成为开发者的优选工具。
|
6月前
|
开发框架 安全 前端开发
Go Web开发框架实践:模板渲染与静态资源服务
Gin 是一个功能强大的 Go Web 框架,不仅适用于构建 API 服务,还支持 HTML 模板渲染和静态资源托管。它可以帮助开发者快速搭建中小型网站,并提供灵活的模板语法、自定义函数、静态文件映射等功能,同时兼容 Go 的 html/template 引擎,具备高效且安全的页面渲染能力。
|
6月前
|
开发框架 JSON 中间件
Go语言Web开发框架实践:使用 Gin 快速构建 Web 服务
Gin 是一个高效、轻量级的 Go 语言 Web 框架,支持中间件机制,非常适合开发 RESTful API。本文从安装到进阶技巧全面解析 Gin 的使用:快速入门示例(Hello Gin)、定义 RESTful 用户服务(增删改查接口实现),以及推荐实践如参数校验、中间件和路由分组等。通过对比标准库 `net/http`,Gin 提供更简洁灵活的开发体验。此外,还推荐了 GORM、Viper、Zap 等配合使用的工具库,助力高效开发。