diff --git a/api/middleware/log_http.go b/api/middleware/log_http.go index 03e4abab..477689b6 100644 --- a/api/middleware/log_http.go +++ b/api/middleware/log_http.go @@ -23,31 +23,44 @@ type LogHTTPConfig struct { UseGzip bool } -// getFileLogger returns file logger for http requests or creates new if not exists. -func (h *LogHTTPConfig) getFileLogger() (*zap.Logger, error) { - c := newLoggerConfig() - c.OutputPaths = []string{h.OutputPath} - if h.OutputPath != StdoutPath && h.OutputPath != StderrPath && h.OutputPath != "" { - err := h.registerOutputSink() - if err != nil { - return nil, err - } - c.OutputPaths[0] = SinkName + ":" + h.OutputPath - } - - return c.Build() +type fileLogger struct { + *zap.Logger + logRoller *lumberjack.Logger } -// registerOutputSink registers sink for logger file output. -func (h *LogHTTPConfig) registerOutputSink() error { - logRoller := &lumberjack.Logger{ - Filename: h.OutputPath, - MaxSize: h.MaxLogSize, - Compress: h.UseGzip, +var filelog = fileLogger{} + +// newFileLogger returns registers zap sink and returns new fileLogger. +func newFileLogger(conf *LogHTTPConfig) (fileLogger, error) { + var flog = fileLogger{} + c := flog.newLoggerConfig() + c.OutputPaths = []string{conf.OutputPath} + if conf.OutputPath != StdoutPath && conf.OutputPath != StderrPath && conf.OutputPath != "" { + err := flog.registerOutputSink(conf) + if err != nil { + return flog, err + } + c.OutputPaths[0] = SinkName + ":" + conf.OutputPath + } + log, err := c.Build() + if err != nil { + return flog, err + } + flog.Logger = log + + return flog, nil +} + +// registerOutputSink creates and registers sink for logger file output. +func (f *fileLogger) registerOutputSink(conf *LogHTTPConfig) error { + f.logRoller = &lumberjack.Logger{ + Filename: conf.OutputPath, + MaxSize: conf.MaxLogSize, + Compress: conf.UseGzip, } err := zap.RegisterSink(SinkName, func(_ *url.URL) (zap.Sink, error) { return lumberjackSink{ - Logger: logRoller, + Logger: f.logRoller, }, nil }) if err != nil { @@ -57,6 +70,7 @@ func (h *LogHTTPConfig) registerOutputSink() error { return nil } +// Implementation of zap.Sink for using lumberjack. type lumberjackSink struct { *lumberjack.Logger } @@ -65,10 +79,29 @@ func (lumberjackSink) Sync() error { return nil } +func ReloadFileLogger(conf *LogHTTPConfig) error { + if filelog.logRoller == nil { + return nil + } + filelog.logRoller.MaxSize = conf.MaxLogSize + filelog.logRoller.Compress = conf.UseGzip + + if filelog.logRoller.Filename != conf.OutputPath { + filelog.logRoller.Filename = conf.OutputPath + if err := filelog.logRoller.Rotate(); err != nil { + return err + } + } + + return nil +} + // LogHTTP logs http parameters from s3 request. func LogHTTP(l *zap.Logger, config *LogHTTPConfig) Func { - fileLogger, err := config.getFileLogger() + var err error + filelog, err = newFileLogger(config) if err != nil { + l.Warn(logs.FailedToInitializeHTTPLogger) return func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { h.ServeHTTP(w, r) @@ -81,7 +114,7 @@ func LogHTTP(l *zap.Logger, config *LogHTTPConfig) Func { h.ServeHTTP(w, r) return } - var httplog = fileLogger.With( + var httplog = filelog.With( zap.String("from", r.RemoteAddr), zap.String("URI", r.RequestURI), zap.String("method", r.Method), @@ -102,7 +135,7 @@ func LogHTTP(l *zap.Logger, config *LogHTTPConfig) Func { } // newLoggerConfig creates new zap.Config with disabled base fields. -func newLoggerConfig() zap.Config { +func (*fileLogger) newLoggerConfig() zap.Config { c := zap.NewProductionConfig() c.DisableCaller = true c.DisableStacktrace = true diff --git a/api/middleware/log_http_stub.go b/api/middleware/log_http_stub.go index 175800db..556f030c 100644 --- a/api/middleware/log_http_stub.go +++ b/api/middleware/log_http_stub.go @@ -26,6 +26,6 @@ func LogHTTP(l *zap.Logger, _ *LogHTTPConfig) Func { } } -func ReloadFileLogger(conf *LogHTTPConfig) error { +func ReloadFileLogger(_ *LogHTTPConfig) error { return nil } diff --git a/docs/configuration.md b/docs/configuration.md index b9c00e03..1910b24f 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -404,9 +404,9 @@ http_logging: |----------------|--------|---------------|---------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `enabled` | bool | yes | false | Flag to enable the logger. | | `max_body` | int | yes | 1024 | Max body size for log output in bytes. | -| `max_log_size` | int | no | 50 | Log file size threshold (in megabytes) to be moved in backup file. After reaching threshold, initial filename is appended with timestamp. And new empty file with initial name is created. | -| `gzip` | bool | no | false | Whether to enable Gzip compression for backup log files. | -| `destination` | string | no | stdout | Specify path for log output. Accepts log file path, or "stdout" and "stderr" reserved words to print in output streams. | +| `max_log_size` | int | yes | 50 | Log file size threshold (in megabytes) to be moved in backup file. After reaching threshold, initial filename is appended with timestamp. And new empty file with initial name is created. | +| `gzip` | bool | yes | false | Whether to enable Gzip compression for backup log files. | +| `destination` | string | yes | stdout | Specify path for log output. Accepts log file path, or "stdout" and "stderr" reserved words to print in output streams. | ### `cache` section diff --git a/internal/logs/logs.go b/internal/logs/logs.go index ca6e5cc6..9fb65ee9 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -106,8 +106,10 @@ const ( FailedToResolveCID = "failed to resolve CID" // Debug in ../../api/middleware/metrics.go RequestStart = "request start" // Info in ../../api/middleware/reqinfo.go RequestHTTP = "http request" // Info in ../../api/middleware/log_http.go + FailedToInitializeHTTPLogger = "failed to initialize http logger" // Warn in ../../api/middleware/log_http.go + FailedToReloadHTTPFileLogger = "failed to reload http file logger" // Warn in ../../api/middleware/log_http.go + FailedToGetRequestBody = "failed to get request body" // Warn in ../../api/middleware/log_http.go LogHTTPDisabledInThisBuild = "http logging disabled in this build" // Warn in ../../api/middleware/log_http_stub.go - FailedToGetRequestBody = "failed to get request body" // Warn in ../../api/middleware/log_http_stub.go FailedToUnescapeObjectName = "failed to unescape object name" // Warn in ../../api/middleware/reqinfo.go CouldNotHandleMessage = "could not handle message" // Error in ../../api/notifications/controller.go CouldNotACKMessage = "could not ACK message" // Error in ../../api/notifications/controller.go