微服务框架 go-zero logx 日志组件剖析

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 微服务框架 go-zero logx 日志组件剖析

addTenant api 和 rpc 的实现

上一篇我们说到咱们还剩下 addTenant 功能还未实现,不知道有没有兄弟感兴趣去实验一波的,本篇文章进行简要补充

根据上一篇文章分析,其实我们只需要执行如下几步即可:

  1. 编写 tenant.api,提供外部 addTenant 的 http 接口
  • 编写 tenant.api

提供一个 POST http 的接口 /api/tenant/addtenant

type (
        AddTenantReq {
                Name string `json:"name"`
                Addr string `json:"addr"`
        }
        AddTenantRsp {
                Id string `json:"id"`
        }
)
service tenant {
        @handler addTenant
        post /api/tenant/addtenant(AddTenantReq) returns (AddTenantRsp)
  • goctl 生成api代码
goctl api go -api tenant.api  -dir .
  1. 修改 api 的配置和逻辑层,让 api 层去调用之前写好的rpc接口 即可

对于配置可以模仿上一篇文章 order.api 的配置进行修改,另外只需要调整 addTenant 的 logic 层即可

func (l *AddTenantLogic) AddTenant(req *types.AddTenantReq) (*types.AddTenantRsp, error) {
   // todo: add your logic here and delete this line
   rsp,err :=l.svcCtx.TenantRpc.AddTenant(l.ctx, &tenant.AddTenantReq{
      Name: req.Name,
      Addr: req.Addr,
   })
   if err !=nil{
      return nil,err
   }
   return &types.AddTenantRsp{Id: rsp.Id},nil
}

具体的代码案例可以访问地址:https://github.com/qingconglaixueit/my_test_Demo

下面我们来看是 go-zero 中 日志组件 logx 的剖析

logx 日志组件剖析

对于 logx 日志组件,分别从如下几个方面来聊一聊我的理解,如果描述有不当的地方,还请多加评论多加交流

  • Go-zero 中 logx 是如何使用的?
  • Logx 基本的数据结构
  • Logx 的默认接口实现
  • Logx 日志存储位置,以及自定义存储日志位置的实现
  • Logx 实现自定义接口的方式

Go-zero 中 logx 是如何使用的?

我们以之前的 demo ,关于 tenant 的 rpc 部分作为例子,追踪一下代码,是如何走到日志部分的逻辑的

可以看到在 tenant.go 的文件中,做的是服务的启动

zrpc.MustNewServer 实际上是调用 go-zero 的 zrpc 包 的 NewServer 函数,传入的参数是

  • c RpcServerConf , 我们 rpc 服务的配置,就是咱们项目中的 etc/tenant.yaml

今天不聊关于 RpcServerConf 的结构,咱们重点说说 logx

  • register internal.RegisterFn 注册服务的回调函数

NewServer 函数做了如下几件事情:

  • RpcServerConf 配置数据的有效性检查
  • 初始化 metrics 的 options
  • 设置服务名,注册 etcd 服务,服务名就是上述配置文件中的 Name 字段
  • c.SetUp() 启动整个服务

对于 logx 日志组件的启动就是在 c.SetUp() 中完成

Logx 基本的数据结构

继续看到 logx.SetUp() 中的具体实现 , 函数需要传入的数据结构是这样的 LogConf

type LogConf struct {
   ServiceName         string `json:",optional"`
   Mode                string `json:",default=console,options=[console,file,volume]"`
   Encoding            string `json:",default=json,options=[json,plain]"`
   TimeFormat          string `json:",optional"`
   Path                string `json:",default=logs"`
   Level               string `json:",default=info,options=[info,error,severe]"`
   Compress            bool   `json:",optional"`
   KeepDays            int    `json:",optional"`
   StackCooldownMillis int    `json:",default=100"`
}
  • ServiceName:设置服务名称,可选。在 volume 模式下,该名称用于生成日志文件。在 rest/zrpc 服务中,名称将被自动设置为 restzrpc 的名称。
  • Mode:输出日志的模式,默认是console
  • console 模式将日志写到 stdout/stderr
  • file 模式将日志写到 Path 指定目录的文件中
  • volume 模式在 docker 中使用,将日志写入挂载的卷中
  • Encoding: 指示如何对日志进行编码,默认是json
  • json模式以 json 格式写日志
  • plain模式用纯文本写日志,并带有终端颜色显示
  • TimeFormat:自定义时间格式,可选。默认是 2006-01-02T15:04:05.000Z07:00
  • Path:设置日志路径,默认为 logs
  • Level: 用于过滤日志的日志级别。默认为info
  • info,所有日志都被写入
  • error, info 的日志被丢弃
  • severe, infoerror 日志被丢弃,只有 severe 日志被写入
  • Compress: 是否压缩日志文件,只在 file 模式下工作
  • KeepDays:日志文件被保留多少天,在给定的天数之后,过期的文件将被自动删除。对 console 模式没有影响
  • StackCooldownMillis:多少毫秒后再次写入堆栈跟踪。用来避免堆栈跟踪日志过多

另外对于 SetUp 函数做了如下几件事:

  • 设定日志等级
  • 初始化时间格式
  • 根据编码方式初始化存储日志编码类型
  • 根据设定的模式来初始化 Writer 句柄

Logx 的默认接口实现

对于 logx 打印日志的具体接口定义在:logx 包的 logger.go 文件中

对于上述接口,根据需要传递的参数我们可以分为如下几类:

  • Error, Info, Slow: 将任何类型的信息写进日志,使用 fmt.Sprint(...) 来转换为 string
  • Errorf, Infof, Slowf: 将指定格式的信息写入日志
  • Errorv, Infov, Slowv: 将任何类型的信息写入日志,用 json marshal 编码
  • Errorw, Infow, Sloww: 写日志,并带上给定的 key:value 字段
  • WithContext:将给定的 ctx 注入日志信息,例如用于记录 trace-idspan-id
  • WithDuration: 将指定的时间写入日志信息中,字段名为 duration

例如接口名后缀带有 w 的,是需要咱们传入 key:value 的,例如传入的结构是这样的:

实际上我们可以看到在 logx 源码中,其实有很多文件都已经根据自己的使用情况去实现了上述 Logger 接口

举一个 traceLogger 的例子

实际上我们可以直接看到,我们之前实现的 GetTenantrpc方法

我们可以看到当调用了NewGetTenantLogic 方法之后,实际上是会调用 logx.WithContext(ctx) 初始化一个 traceLogger 的句柄

traceLogger 实现了上述 Logger 接口, 因此,当我们需要在 rpc 中打印日志的时候,我们可以这样来使用

这个时候,实际上是调用的 traceLogger 对应的实现代码

我们可以看到,打印出来的日志,是我们所期望的信息

此处的字段对应含义是这样的:

  • Timestamp

时间戳

  • Level

日志等级

  • Duration

时间间隔

  • Caller

日志调用者

  • Content

具体的日志信息

仔细查看上述日志,我们可以发现还有 trace 和 span 字段也打印出来了,但是 logEntry 为什么没有定义呢

咱们稍微追一下代码,不难看出,是 traceLogger 内部的 info 函数进行日志信息的拼接

Logx 自定义存储日志位置 和 实现自定义接口的方式

Logx 自定义存储日志位置 和 实现自定义接口的方式其实我在这里就不需要过多的解释了,简单说明一下实现手段就可以了,有必要的话咱们可以查看 go-zero 官方文档 https://go-zero.dev/cn/docs/component/logx/

自定义存储日志位置

对于咱们需要修改日志的输出位置,实际上我们可以仔细思考一下,对于日志的数据,go-zero 还是使用的 golangio包中的 Writer 接口

咱们只需要定义对象,去实现 Writer 接口 中的 Write(p []byte) (n int, err error) 方法就可以了

官网也给了我们例子,例如咱们实现输出的日志往 kafka 里面吐,我们就可以这样

实现自定义接口

实现自定义接口,咱们其实刚才看 traceLogger 的实现方式,我们就能领悟到, traceLogger 去实现 Logger 接口中的方法,并且加入自己自定义的逻辑,例如加上了 trace 和 span

那么对于我们自定义接口,其实也是非常容易的,照葫芦画瓢即可了

\

感谢阅读,欢迎交流,点个赞,关注一波 再走吧

欢迎点赞,关注,收藏

朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力

好了,本次就到这里

技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。

我是阿兵云原生,欢迎点赞关注收藏,下次见~

可以进入地址进行体验和学习:https://xxetb.xet.tech/s/3lucCI

相关实践学习
日志服务之数据清洗与入湖
本教程介绍如何使用日志服务接入NGINX模拟数据,通过数据加工对数据进行清洗并归档至OSS中进行存储。
相关文章
|
1天前
|
存储 Web App开发 Java
《手把手教你》系列基础篇(九十五)-java+ selenium自动化测试-框架之设计篇-java实现自定义日志输出(详解教程)
【7月更文挑战第13天】这篇文章介绍了如何在Java中创建一个简单的自定义日志系统,以替代Log4j或logback。
11 5
|
3天前
|
消息中间件 Java 开发者
Spring Cloud微服务框架:构建高可用、分布式系统的现代架构
Spring Cloud是一个开源的微服务框架,旨在帮助开发者快速构建在分布式系统环境中运行的服务。它提供了一系列工具,用于在分布式系统中配置、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态等领域的支持。
20 5
|
6天前
|
XML Java 测试技术
《手把手教你》系列基础篇(九十一)-java+ selenium自动化测试-框架设计基础-Logback实现日志输出-下篇(详解教程)
【7月更文挑战第9天】在Java项目中,使用Logback配置可以实现日志按照不同包名输出到不同的文件,并且根据日志级别分开记录。
20 4
|
7天前
|
XML Java 测试技术
《手把手教你》系列基础篇(九十)-java+ selenium自动化测试-框架设计基础-Logback实现日志输出-中篇(详解教程)
【7月更文挑战第8天】这篇教程介绍了如何使用Logback将Java应用的日志输出到文件中。首先,通过创建`logback.xml`配置文件,设置`FileAppender`来指定日志文件路径和格式。然后,提供了一个`RollingFileAppender`的例子,用于每日生成新的日志文件并保留一定天数的历史记录。文中包含配置文件的XML代码示例,并展示了控制台输出和生成的日志文件内容。教程最后提到了一些可能遇到的问题及解决建议。
15 0
《手把手教你》系列基础篇(九十)-java+ selenium自动化测试-框架设计基础-Logback实现日志输出-中篇(详解教程)
|
11天前
|
XML 测试技术 数据格式
《手把手教你》系列基础篇(八十五)-java+ selenium自动化测试-框架设计基础-TestNG自定义日志-下篇(详解教程)
【7月更文挑战第3天】TestNG教程展示了如何自定义日志记录。首先创建一个名为`TestLog`的测试类,包含3个测试方法,其中一个故意失败以展示日志。使用`Assert.assertTrue`和`Reporter.log`来记录信息。接着创建`CustomReporter`类,继承`TestListenerAdapter`,覆盖`onTestFailure`, `onTestSkipped`, 和 `onTestSuccess`,在这些方法中自定义日志输出。
27 6
|
8天前
|
Java 关系型数据库 测试技术
《手把手教你》系列基础篇(八十九)-java+ selenium自动化测试-框架设计基础-Logback实现日志输出-上篇(详解教程)
【7月更文挑战第7天】Apache Log4j2的安全漏洞促使考虑使用logback作为替代的日志框架。Logback由log4j创始人设计,提供更好的性能,更低的内存使用,并且能够自动重载配置文件。它分为logback-core、logback-classic(实现了SLF4J API)和logback-access(用于Servlet容器集成)三个模块。配置涉及Logger、Appender(定义日志输出目的地)和Layout(格式化日志)。
15 1
|
11天前
|
Java 测试技术 Apache
《手把手教你》系列基础篇(八十六)-java+ selenium自动化测试-框架设计基础-Log4j实现日志输出(详解教程)
【7月更文挑战第4天】Apache Log4j 是一个广泛使用的 Java 日志框架,它允许开发者控制日志信息的输出目的地、格式和级别。Log4j 包含三个主要组件:Loggers(记录器)负责生成日志信息,Appenders(输出源)确定日志输出的位置(如控制台、文件、数据库等),而 Layouts(布局)则控制日志信息的格式。通过配置 Log4j,可以灵活地定制日志记录行为。
27 4
|
13天前
|
监控 负载均衡 Java
Spring Boot与微服务治理框架的集成
Spring Boot与微服务治理框架的集成
|
9天前
|
XML Java 测试技术
《手把手教你》系列基础篇(八十八)-java+ selenium自动化测试-框架设计基础-Log4j 2实现日志输出-下篇(详解教程)
【7月更文挑战第6天】本文介绍了如何使用Log4j2将日志输出到文件中,重点在于配置文件的结构和作用。配置文件包含两个主要部分:`appenders`和`loggers`。`appenders`定义了日志输出的目标,如控制台(Console)或其他文件,如RollingFile,设置输出格式和策略。`loggers`定义了日志记录器,通过`name`属性关联到特定的类或包,并通过`appender-ref`引用`appenders`来指定输出位置。`additivity`属性控制是否继承父logger的配置。
15 0
|
10天前
|
XML Java 测试技术
《手把手教你》系列基础篇(八十七)-java+ selenium自动化测试-框架设计基础-Log4j 2实现日志输出-上篇(详解教程)
【7月更文挑战第5天】Apache Log4j 2是一个日志框架,它是Log4j的升级版,提供了显著的性能提升,借鉴并改进了Logback的功能,同时修复了Logback架构中的问题。Log4j2的特点包括API与实现的分离,支持SLF4J,自动重新加载配置,以及高级过滤选项。它还引入了基于lambda表达式的延迟评估,低延迟的异步记录器和无垃圾模式。配置文件通常使用XML,但也可以是JSON或YAML,其中定义了日志级别、输出目的地(Appender)和布局(Layout)。
17 0