日志
Hertz 提供打印日志的方式,默认打在标准输出。实现在 pkg/common/hlog
中,Hertz 同时也提供了若干全局函数,例如 hlog.Info
、hlog.Errorf
、hlog.CtxTracef
等,用于调用默认 logger 的相应方法。
如何打印日志
hertz 中可以直接调用 pkg/common/hlog
包下的方法打日志,该方法会调用 defaultLogger
上对应的方法。如实现一个打印 AccessLog 的中间件。
func AccessLog() app.HandlerFunc {
return func(ctx context.Context, c *app.RequestContext) {
start := time.Now()
c.Next(ctx)
end := time.Now()
latency := end.Sub(start).Microseconds
hlog.CtxTracef(c, "status=%d cost=%d method=%s full_path=%s client_ip=%s host=%s",
c.Response.StatusCode(), latency,
c.Request.Header.Method(), c.Request.URI().PathOriginal(), c.ClientIP(), c.Request.Host())
}
}
重定向默认 logger 的输出
可以使用 hlog.SetOutput
来重定向 hlog 提供的默认 logger 的输出。
例如,要把默认 logger 的输出重定向到启动路径下的 ./output.log
,可以这样实现:
package main
import (
"os"
"github.com/cloudwego/hertz/pkg/common/hlog"
)
func main() {
f, err := os.OpenFile("./output.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
panic(err)
}
defer f.Close()
hlog.SetOutput(f)
... // continue to set up your server
}
logger 的默认输出位置为 os.stdout,在重定向后将不会在终端输出。
如果想同时输出到终端和路径,可参考以下代码:
package main
import (
"io"
"os"
"github.com/cloudwego/hertz/pkg/common/hlog"
)
func main() {
f, err := os.OpenFile("./output.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
panic(err)
}
defer f.Close()
fileWriter := io.MultiWriter(f,os.Stdout)
hlog.SetOutput(fileWriter)
... // continue to set up your server
}
设置 logLevel
可以使用 hlog.SetLevel
来设置日志等级,高于该日志等级的日志才能够被打印出来。
hlog.SetLevel(hlog.LevelInfo)
目前支持的日志等级有
LevelTrace
LevelDebug
LevelInfo
LevelNotice
LevelWarn
LevelError
LevelFatal
hlog 打印日志并指定日志的 field
以 zerolog 为例,zerolog 中实现了这样的函数:
package main
import (
"bytes"
"github.com/cloudwego/hertz/pkg/common/json"
hertzZerolog "github.com/hertz-contrib/logger/zerolog"
)
func main() {
b := &bytes.Buffer{}
l := hertzZerolog.New(hertzZerolog.WithField("service", "logging"))
l.SetOutput(b)
l.Info("foobar")
type Log struct {
Level string `json:"level"`
Service string `json:"service"`
Message string `json:"message"`
}
log := &Log{}
err := json.Unmarshal(b.Bytes(), log)//log.service=="logging"
}
而在 zap 和 logrus 中并未直接实现这样的函数,需要手动添加原始 option
以 zap 为例:
package main
import (
"bytes"
"github.com/cloudwego/hertz/pkg/common/json"
hertzzap "github.com/hertz-contrib/logger/zap"
"go.uber.org/zap"
)
func main() {
b := &bytes.Buffer{}
l := hertzzap.NewLogger(hertzzap.WithZapOptions(zap.Fields(zap.String("service", "logging"))))
l.SetOutput(b)
l.Info("foobar")
type Log struct {
Level string `json:"level"`
Service string `json:"service"`
Message string `json:"message"`
}
log := &Log{}
err := json.Unmarshal(b.Bytes(), log) //log.service=="logging"
}
关闭 Engine 错误日志
在生产环境中可能会遇到 error when reading request headers
类似的错误,这类错误往往由于 client 侧不规范的行为导致。对于 server 来说除了通过 client IP 定位到具体 client 并告知其整改(如果可以的话)以外,能够做的并不多。
因此 Hertz 提供了一个配置,在初始化时添加如下配置即可关闭这些日志
hlog.SetSilentMode(true)
设置 trace
hertz-contrib/logger 下的 logger 不具备直接的 trace 功能。
可以参照 Trace 文档的日志部分。
日志拓展
目前 hlog 支持 zap , logrus 和 zerolog 的拓展使用,日志拓展 详见。