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"
相关推荐
wuyikeer1 小时前
Spring Framework 中文官方文档
java·后端·spring
Victor3561 小时前
MongoDB(61)如何避免大文档带来的性能问题?
后端
Victor3562 小时前
MongoDB(62)如何避免锁定问题?
后端
wuyikeer2 小时前
Spring BOOT 启动参数
java·spring boot·后端
子木HAPPY阳VIP3 小时前
Ubuntu 22.04 VMware 设置固定IP配置
人工智能·后端·目标检测·机器学习·目标跟踪
人间打气筒(Ada)3 小时前
如何基于 Go-kit 开发 Web 应用:从接口层到业务层再到数据层
开发语言·后端·golang
开心就好20253 小时前
使用Wireshark进行TCP数据包抓包分析:三次握手与四次挥手详解
后端·ios
用户4419395054873 小时前
OpenClaw服务器部署保姆级教程
后端
zdl6863 小时前
springboot集成onlyoffice(部署+开发)
java·spring boot·后端
Soofjan3 小时前
sync.Mutex讲解
后端