net/http设置自定义记录器

net/http设置自定义记录器,http,go,logging,Http,Go,Logging,我想以自己的格式记录net/http中的错误。在net/http包中,我找到了结构: 我想用我自己的实现替代logger: type AppLogger struct { log *zap.SugaredLogger } func (l *AppLogger) Error(message string, keyAndValues ...interface{}) { l.log.Errorw(message, keyAndValues...) } 正确的实施方式是什么 更新:

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

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

type AppLogger struct {
    log *zap.SugaredLogger
}

func (l *AppLogger) Error(message string, keyAndValues ...interface{}) {
    l.log.Errorw(message, keyAndValues...)
}
正确的实施方式是什么


更新:

我有以下配置的记录器:

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"}}
}
问题:

  • serverJsonWriter
    方法的主体应该是什么
  • 我是否应该检索
    zap
    io.Writer以传递它
    log.Logger
    ?如何做到这一点

  • 这是很容易做到的,因为该类型保证每个日志消息都通过一个
    Writer.Write()
    调用传递到目标:

    每个日志记录操作都对编写器的写入方法进行一次调用。一个记录器可以从多个goroutine同时使用;它保证序列化对写入程序的访问

    因此,基本上您只需要创建一个实现
    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


    请参阅类似问题:

    您可以使用
    zap.NewStdLog()
    获取
    *log.Logger
    的新实例


    不幸的是,这是不可能的,因为
    *log.Logger
    是一种具体类型。你能做的最接近的事情就是使用一个记录到你自己的
    io.Writer
    的记录器。有一种方法可以使log.logger成为一个接口,您想如何将
    net/http
    记录的单个错误消息转换为
    message
    keyAndValues
    ,这是
    SugaredLogger.Errorw()
    的参数?@icza,我将跳过
    keyAndValues
    。我只想从
    net/http
    server := &http.Server{
        Addr:     addr,
        Handler:  handler,
        ErrorLog: logger.New(&fwdToZapWriter{logger}, "", 0),
    }
    
    logger := zap.NewExample()
    defer logger.Sync()
    
    std := zap.NewStdLog(logger)
    std.Print("standard logger wrapper")
    
    // Output:
    // {"level":"info","msg":"standard logger wrapper"}