go-zero的日志配置——logx

01 背景

go-zero是一个集成了各种工程实践的 web 和 rpc 框架,其集成的gooctl生成工具,可以为我们快速生成代码,加速开发的过程。

go-zero框架有一个自己的日志包logx(logc是logx的封装)。 查阅go-zero框架的文档,日志配置的使用方法是:

go 复制代码
var c logx.LogConf
logx.MustSetup(c)

logx.Info(context.Background(), "log")
// do your job

然而文档里并没有介绍如何在goctl工具生成的HTTP服务代码中配置日志,我也就在这里遇到了个小坑。以下是我开始时写的日志配置相关的代码,然而,日志配置并没有生效,输出的日志是json格式的(默认为json格式)。

go 复制代码
// ./etc/serice.yaml
LogConf:
  ServiceName: "http_service"
  Encoding: "plain"
  Level: "debug"
  Path: "http_service/logs"

// ./internal/config/config.go
type Config struct {
    rest.RestConf
    Auth struct {
        AccessSecret string
        AccessExpire int64
    }
    LogConf logx.LogConf
}

// ./service.go
func main() {
    flag.Parse()

    var c config.Config
    conf.MustLoad(*configFile, &c)

    server := rest.MustNewServer(c.RestConf)
    defer server.Stop()

    ctx := svc.NewServiceContext(c)
    handler.RegisterHandlers(server, ctx)

    logx.MustSetup(c.LogConf)
    
    fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
    server.Start()
}

02 寻因过程

我首先尝试在google上搜索看看有没有其他同学发表过这个logx日志包的使用,然而并没有搜索到相关的信息。接着尝试了在github上搜索logx.MustSetup,找到了一些大家是如何配置日志的,但是感觉仍然没搞清楚应该如何正确配置日志。

最后还是得自己老老实实看看源码。可以看见,go-zero为func SetUp(c LogConf) (err error)这个log的设置函数使用了单例模式:

go 复制代码
func SetUp(c LogConf) (err error) {
    setupOnce.Do(func() {
        setupLogLevel(c)
        // ...
        switch c.Mode {
        case fileMode:
            err = setupWithFiles(c)
        case volumeMode:
            err = setupWithVolume(c)
        default:
            setupWithConsole()
        }
    })
    return
}

于是我猜测会不会是SetUp(c LogConf)函数已经调用过了,所以设置并没有生效。果然,其实在server := rest.MustNewServer(c.RestConf)中就已经调用过了这个SetUp()函数了:

go 复制代码
func MustNewServer(c RestConf, opts ...RunOption) *Server {
    server, err := NewServer(c, opts...)
    if err != nil {
        logx.Must(err)
    }
    return server
}

func NewServer(c RestConf, opts ...RunOption) (*Server, error) {
    if err := c.SetUp(); err != nil {
        return nil, err
    }
    // ...
    return server, nil
}

func (sc ServiceConf) SetUp() error {
    if len(sc.Log.ServiceName) == 0 {
        sc.Log.ServiceName = sc.Name
    }
    if err := logx.SetUp(sc.Log); err != nil {
        return err
    }
    // ...
    return nil
}

同时,我们可以看到ServiceConf结构体中包含了日志配置结构体logx.LogConf:

go 复制代码
    ServiceConf struct {
    Name       string
    Log        logx.LogConf
    Mode       string `json:",default=pro,options=dev|test|rt|pre|pro"`
    MetricsUrl string `json:",optional"`
    // Deprecated: please use DevServer
    Prometheus prometheus.Config `json:",optional"`
    Telemetry  trace.Config      `json:",optional"`
    DevServer  DevServerConfig   `json:",optional"`
	}

03 解决

从源码中可以看到,logx.LogConf在ServiceConf结构体中相应的成员名为Log,所以配置文件service.yaml中与日志相关的配置应该写为:

yaml 复制代码
Log:
  ServiceName: "http_service"
  Mode: "console"
  Encoding: "plain"
  Level: "debug"
  Path: "http_service/logs"
相关推荐
码事漫谈10 小时前
C++小白最容易踩的10个坑(附避坑指南)
后端
码事漫谈10 小时前
性能提升11.4%!C++ Vector的reserve()方法让我大吃一惊
后端
稚辉君.MCA_P8_Java11 小时前
Gemini永久会员 Java中的四边形不等式优化
java·后端·算法
稚辉君.MCA_P8_Java11 小时前
通义 插入排序(Insertion Sort)
数据结构·后端·算法·架构·排序算法
q***697711 小时前
【Spring Boot】统一数据返回
java·spring boot·后端
v***598311 小时前
DeepSeek API 调用 - Spring Boot 实现
windows·spring boot·后端
Hollis Chuang11 小时前
Spring Boot 4.0 正式发布,人麻了。。。
java·spring boot·后端·spring
Moshow郑锴11 小时前
实战分享:用 SpringBoot-API-Scheduler 构建 API 监控闭环 —— 从断言验证到智能警报
java·spring boot·后端·任务调度
金融数据出海12 小时前
日本股票市场渲染 KlineCharts K 线图
前端·后端
1***t82712 小时前
将 vue3 项目打包后部署在 springboot 项目运行
java·spring boot·后端