net / http set custom logger - PullRequest
       25

net / http set custom logger

0 голосов
/ 12 сентября 2018

Я хотел бы регистрировать ошибки из net / http в моем собственном формате. В пакете net / http я нашел Сервер struct:

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

Я бы хотел заменить регистратор своей собственной реализацией:

type AppLogger struct {
    log *zap.SugaredLogger
}

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

Как правильно это реализовать?


Обновление:

У меня есть zap logger со следующей конфигурацией:

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. Должен ли я получить zap io.Writer, чтобы передать его log.Logger? Как это сделать?

1 Ответ

0 голосов
/ 12 сентября 2018

Это легко выполнимо, потому что тип log.Logger гарантирует, что каждое сообщение журнала доставляется в пункт назначения io.Writer с помощью одного Writer.Write() вызова:

Каждая операция записи в журнал делает один вызов метода записи Writer. Logger может использоваться одновременно с несколькими программами; это гарантирует сериализацию доступа к 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.

См. Аналогичный вопрос: Go: Создать интерфейс io.Writer для входа в базу данных mongodb

...