go-zero 微服务框架如何将日志输出到文件
在 go-zero 中,默认日志是输出到 控制台 的,项目运行起来后,往往都是输出到日志,今天看看 go-zero 框架的 API 功能的日志配置。
目前网上关于 go-zero 的配置相对少,找了一圈,没找到更多的资料或者案例,而且官方给的 doc 又是一笔带过,不多说,下面看看吧。
我们直接给出对应的配置:userapi.yaml
Name: userapi-api
Host: 0.0.0.0
Port: 8888
Auth:
AccessSecret: 84a8a776-e447-4870-83ea-a17e8d28c76d
AccessExpire: 3600
# 需要以 Log 作为 section
Log:
Mode: file
Level: debug
Path: ./logs
Rotation: daily
然后运行项目即可看到在项目中出现对应的不同 log:
为什么需要这样配置呢,追代码吧。
先看看项目启动的代码部分:
userapi.go
package main
import (
"flag"
"fmt"
"userapiv1/internal/config"
"userapiv1/internal/handler"
"userapiv1/internal/svc"
"github.com/zeromicro/go-zero/core/conf"
"github.com/zeromicro/go-zero/rest"
)
var configFile = flag.String("f", "etc/userapi-api.yaml", "the config file")
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)
// go-zero version >= v1.7.0
//logx.AddWriter(logx.NewWriter(os.Stdout)) // 添加控制台输出
fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
server.Start()
}
go-zero/rest/server.go
func MustNewServer(c RestConf, opts ...RunOption) *Server {
server, err := NewServer(c, opts...) // here
if err != nil {
log.Fatal(err)
}
return server
}
// NewServer returns a server with given config of c and options defined in opts.
// Be aware that later RunOption might overwrite previous one that write the same option.
func NewServer(c RestConf, opts ...RunOption) (*Server, error) {
if err := c.SetUp(); err != nil { // here
return nil, err
}
server := &Server{
ngin: newEngine(c),
router: router.NewRouter(),
}
opts = append([]RunOption{WithNotFoundHandler(nil)}, opts...)
for _, opt := range opts {
opt(server)
}
return server, nil
}
go-zero/core/service/serviceconf.go
func (sc ServiceConf) SetUp() error {
if len(sc.Log.ServiceName) == 0 {
sc.Log.ServiceName = sc.Name
}
if err := logx.SetUp(sc.Log); err != nil { // here
return err
}
sc.initMode()
prometheus.StartAgent(sc.Prometheus)
if len(sc.Telemetry.Name) == 0 {
sc.Telemetry.Name = sc.Name
}
trace.StartAgent(sc.Telemetry)
proc.AddShutdownListener(func() {
trace.StopAgent()
})
if len(sc.MetricsUrl) > 0 {
stat.SetReportWriter(stat.NewRemoteWriter(sc.MetricsUrl))
}
devserver.StartAgent(sc.DevServer)
return nil
}
可以看到这里完成日志的配置,接下来看看具体的结构体:
同文件下:
// A ServiceConf is a service config.
type 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 devserver.Config `json:",optional"`
}
go-zero/core/logx/config.go
// A LogConf is a logging config.
type LogConf struct {
// ServiceName represents the service name.
ServiceName string `json:",optional"`
// Mode represents the logging mode, default is `console`.
// console: log to console.
// file: log to file.
// volume: used in k8s, prepend the hostname to the log file name.
Mode string `json:",default=console,options=[console,file,volume]"`
// Encoding represents the encoding type, default is `json`.
// json: json encoding.
// plain: plain text encoding, typically used in development.
Encoding string `json:",default=json,options=[json,plain]"`
// TimeFormat represents the time format, default is `2006-01-02T15:04:05.000Z07:00`.
TimeFormat string `json:",optional"`
// Path represents the log file path, default is `logs`.
Path string `json:",default=logs"`
// Level represents the log level, default is `info`.
Level string `json:",default=info,options=[debug,info,error,severe]"`
// MaxContentLength represents the max content bytes, default is no limit.
MaxContentLength uint32 `json:",optional"`
// Compress represents whether to compress the log file, default is `false`.
Compress bool `json:",optional"`
// Stdout represents whether to log statistics, default is `true`.
Stat bool `json:",default=true"`
// KeepDays represents how many days the log files will be kept. Default to keep all files.
// Only take effect when Mode is `file` or `volume`, both work when Rotation is `daily` or `size`.
KeepDays int `json:",optional"`
// StackCooldownMillis represents the cooldown time for stack logging, default is 100ms.
StackCooldownMillis int `json:",default=100"`
// MaxBackups represents how many backup log files will be kept. 0 means all files will be kept forever.
// Only take effect when RotationRuleType is `size`.
// Even thougth `MaxBackups` sets 0, log files will still be removed
// if the `KeepDays` limitation is reached.
MaxBackups int `json:",default=0"`
// MaxSize represents how much space the writing log file takes up. 0 means no limit. The unit is `MB`.
// Only take effect when RotationRuleType is `size`
MaxSize int `json:",default=0"`
// RotationRuleType represents the type of log rotation rule. Default is `daily`.
// daily: daily rotation.
// size: size limited rotation.
Rotation string `json:",default=daily,options=[daily,size]"`
}
所以兜一圈,你就会发现在 yaml 配置文件中应该以 Log 打头的 section,具体的字段的话,参考 logx.LogConf 字段进行配置。
另外有一点需要说明的是,我用的 go-zero 版本是 v1.5.0,如果需要在 控制台 也输出日志的话,需要在项目启动位置加入以下代码:
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)
// go-zero version >= v1.7.0
//logx.AddWriter(logx.NewWriter(os.Stdout)) // 添加控制台输出
fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
server.Start()
}
有个坑,就是对应的 go-zero 需要版本升级。
以上就是 go-zero 的日志配置,码字不易,希望对大家有用。