net/http 设置自定义记录器

Rud*_*koŭ 5 logging http go

我想以我自己的格式记录来自 net/http 的错误。在 net/http 包中我找到了服务器结构:

type Server struct {
        //...
        ErrorLog *log.Logger
}
Run Code Online (Sandbox Code Playgroud)

我想用我自己的实现替换记录器:

type AppLogger struct {
    log *zap.SugaredLogger
}

func (l *AppLogger) Error(message string, keyAndValues ...interface{}) {
    l.log.Errorw(message, keyAndValues...)
}
Run Code Online (Sandbox Code Playgroud)

实现这个的正确方法是什么?


更新:

我的zap记录器具有以下配置:

cfg := zap.Config{
    Encoding:         encoding,
    Level:            zap.NewAtomicLevelAt(zap.DebugLevel),
    OutputPaths:      []string{"stdout"},
    ErrorOutputPaths: []string{"stdout"},
    EncoderConfig:    encCfg,
}
logger, err := cfg.Build()
Run Code Online (Sandbox Code Playgroud)

它配置为以 json 格式写入。我希望用net/http与 zap 相同的方式编写错误。我创建以下内容:

type serverJsonWriter struct {
    io.Writer
}

// ListenAndServeTLS - with custom log Writer
func ListenAndServeTLS(addr, certFile, keyFile string, handler http.Handler) error {
    server := &http.Server{
        Addr: addr,
        Handler: handler,
        ErrorLog: logger.New(serverJsonWriter{}, "", 0),
    }
}

func (w serverJsonWriter) Write(p []byte) (n int, err error){
    // {"error":{"type":"net/http error","message":"header too long"}}
}
Run Code Online (Sandbox Code Playgroud)

问题:

  1. 方法体应该是什么serverJsonWriter
  2. 我应该检索zapio.Writer 才能传递它吗log.Logger?这个怎么做?

icz*_*cza 6

这很容易做到,因为该类型保证通过一次调用log.Logger将每个日志消息传递到目的地:io.WriterWriter.Write()

每个日志记录操作都会对 Writer 的 Write 方法进行一次调用。Logger 可以在多个 goroutine 中同时使用;它保证对 Writer 的访问进行序列化。

所以基本上你只需要创建一个实现 的类型io.Writer,并且其Write()方法只是调用你的记录器。

这是一个简单的实现,它可以做到这一点:

type fwdToZapWriter struct {
    logger *zap.SugaredLogger
}

func (fw *fwdToZapWriter) Write(p []byte) (n int, err error) {
    fw.logger.Errorw(string(p))
    return len(p), nil
}
Run Code Online (Sandbox Code Playgroud)

就这样。http.Server您可以像这样在您的位置“安装”此编写器:

server := &http.Server{
    Addr:     addr,
    Handler:  handler,
    ErrorLog: logger.New(&fwdToZapWriter{logger}, "", 0),
}
Run Code Online (Sandbox Code Playgroud)

logger上面的例子来自你的例子:logger, err := cfg.Build()

如果您愿意,您可以轻松转发到您的AppLogger而不是logger.

查看类似的问题:Go: Create io.Writer inteface forlogging to mongodb database