一尘不染

net / http设置自定义记录器

go

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

type Server struct {
        //...
        ErrorLog *log.Logger
}

我想用自己的实现代替logger:

type AppLogger struct {
    log *zap.SugaredLogger
}

func (l *AppLogger) Error(message string, keyAndValues ...interface{}) {
    l.log.Errorw(message, keyAndValues...)
}

实施此方法的正确方法是什么?


更新:

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

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

它配置为以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"}}
}

问题:

  1. serverJsonWriter方法的主体应该是什么?
  2. 我应该检索zapio.Writer以便通过它log.Logger吗?这该怎么做?

阅读 166

收藏
2020-07-02

共1个答案

一尘不染

这很容易log.Logger做到,因为该类型可以保证每个日志消息都可以通过io.Writer一次Writer.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
}

就这样。您可以http.Server像这样“安装”该编写器:

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

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

如果你愿意,你可以很容易地转发给你的AppLogger,而不是logger

2020-07-02