mirror of
https://github.com/labstack/echo.git
synced 2024-12-22 20:06:21 +02:00
149 lines
4.7 KiB
Go
149 lines
4.7 KiB
Go
package echo
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"strconv"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Example for Zap (https://github.com/uber-go/zap)
|
|
//func main() {
|
|
// e := echo.New()
|
|
// logger, _ := zap.NewProduction()
|
|
// e.Logger = &ZapLogger{logger: logger}
|
|
//}
|
|
//type ZapLogger struct {
|
|
// logger *zap.Logger
|
|
//}
|
|
//
|
|
//func (l *ZapLogger) Write(p []byte) (n int, err error) {
|
|
// // Note: if `logger` middleware is used it will send json bytes here, and it will not look beautiful at all.
|
|
// l.logger.Info(string(p), zap.String("subsystem", "echo")) // naively log everything as string message.
|
|
// return len(p), nil
|
|
//}
|
|
//
|
|
//func (l *ZapLogger) Error(err error) {
|
|
// l.logger.Error(err.Error(), zap.Error(err), zap.String("subsystem", "echo"))
|
|
//}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Example for Zerolog (https://github.com/rs/zerolog)
|
|
//func main() {
|
|
// e := echo.New()
|
|
// logger := zerolog.New(os.Stdout)
|
|
// e.Logger = &ZeroLogger{logger: &logger}
|
|
//}
|
|
//
|
|
//type ZeroLogger struct {
|
|
// logger *zerolog.Logger
|
|
//}
|
|
//
|
|
//func (l *ZeroLogger) Write(p []byte) (n int, err error) {
|
|
// // Note: if `logger` middleware is used it will send json bytes here, and it will not look beautiful at all.
|
|
// l.logger.Info().Str("subsystem", "echo").Msg(string(p)) // naively log everything as string message.
|
|
// return len(p), nil
|
|
//}
|
|
//
|
|
//func (l *ZeroLogger) Error(err error) {
|
|
// l.logger.Error().Str("subsystem", "echo").Err(err).Msg(err.Error())
|
|
//}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Example for Logrus (https://github.com/sirupsen/logrus)
|
|
//func main() {
|
|
// e := echo.New()
|
|
// e.Logger = &LogrusLogger{logger: logrus.New()}
|
|
//}
|
|
//
|
|
//type LogrusLogger struct {
|
|
// logger *logrus.Logger
|
|
//}
|
|
//
|
|
//func (l *LogrusLogger) Write(p []byte) (n int, err error) {
|
|
// // Note: if `logger` middleware is used it will send json bytes here, and it will not look beautiful at all.
|
|
// l.logger.WithFields(logrus.Fields{"subsystem": "echo"}).Info(string(p)) // naively log everything as string message.
|
|
// return len(p), nil
|
|
//}
|
|
//
|
|
//func (l *LogrusLogger) Error(err error) {
|
|
// l.logger.WithFields(logrus.Fields{"subsystem": "echo"}).Error(err)
|
|
//}
|
|
|
|
// Logger defines the logging interface that Echo uses internally in few places.
|
|
// For logging in handlers use your own logger instance (dependency injected or package/public variable) from logging framework of your choice.
|
|
type Logger interface {
|
|
// Write provides writer interface for http.Server `ErrorLog` and for logging startup messages.
|
|
// `http.Server.ErrorLog` logs errors from accepting connections, unexpected behavior from handlers,
|
|
// and underlying FileSystem errors.
|
|
// `logger` middleware will use this method to write its JSON payload.
|
|
Write(p []byte) (n int, err error)
|
|
// Error logs the error
|
|
Error(err error)
|
|
}
|
|
|
|
// jsonLogger is similar logger formatting implementation as `v4` had. It is not particularly fast or efficient. Only
|
|
// goal it to exist is to have somewhat backwards compatibility with `v4` for Echo internals logging formatting.
|
|
// It is not meant for logging in handlers/middlewares. Use some real logging library for those cases.
|
|
type jsonLogger struct {
|
|
writer io.Writer
|
|
bufferPool sync.Pool
|
|
lock sync.Mutex
|
|
|
|
timeNow func() time.Time
|
|
}
|
|
|
|
func newJSONLogger(writer io.Writer) *jsonLogger {
|
|
return &jsonLogger{
|
|
writer: writer,
|
|
bufferPool: sync.Pool{
|
|
New: func() interface{} {
|
|
return bytes.NewBuffer(make([]byte, 256))
|
|
},
|
|
},
|
|
timeNow: time.Now,
|
|
}
|
|
}
|
|
|
|
func (l *jsonLogger) Write(p []byte) (n int, err error) {
|
|
pLen := len(p)
|
|
if pLen >= 2 && // naively try to avoid JSON values to be wrapped into message
|
|
(p[0] == '{' && p[pLen-2] == '}' && p[pLen-1] == '\n') ||
|
|
(p[0] == '{' && p[pLen-1] == '}') {
|
|
return l.write(p)
|
|
}
|
|
// we log with WARN level as we have no idea what that message level should be. From Echo perspective this method is
|
|
// called when we pass Echo logger to http.Server.ErrorLog and there are problems inside http.Server - which probably
|
|
// deserves at least WARN level.
|
|
return l.printf("INFO", string(p))
|
|
}
|
|
|
|
func (l *jsonLogger) Error(err error) {
|
|
_, _ = l.printf("ERROR", err.Error())
|
|
}
|
|
|
|
func (l *jsonLogger) printf(level string, message string) (n int, err error) {
|
|
buf := l.bufferPool.Get().(*bytes.Buffer)
|
|
buf.Reset()
|
|
defer l.bufferPool.Put(buf)
|
|
|
|
buf.WriteString(`{"time":"`)
|
|
buf.WriteString(l.timeNow().Format(time.RFC3339Nano))
|
|
buf.WriteString(`","level":"`)
|
|
buf.WriteString(level)
|
|
buf.WriteString(`","prefix":"echo","message":`)
|
|
|
|
buf.WriteString(strconv.Quote(message))
|
|
buf.WriteString("}\n")
|
|
|
|
return l.write(buf.Bytes())
|
|
}
|
|
|
|
func (l *jsonLogger) write(p []byte) (int, error) {
|
|
l.lock.Lock()
|
|
defer l.lock.Unlock()
|
|
return l.writer.Write(p)
|
|
}
|