[#369] HTTP logging configuration #433

Merged
nzinkevich merged 1 commit from nzinkevich/frostfs-s3-gw:feature/log_http-config into feature/369 2024-09-04 19:51:14 +00:00
4 changed files with 63 additions and 28 deletions

View file

@ -23,31 +23,44 @@ type LogHTTPConfig struct {
UseGzip bool UseGzip bool
} }
// getFileLogger returns file logger for http requests or creates new if not exists. type fileLogger struct {
func (h *LogHTTPConfig) getFileLogger() (*zap.Logger, error) { *zap.Logger
c := newLoggerConfig() logRoller *lumberjack.Logger
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()
} }
// registerOutputSink registers sink for logger file output. var filelog = fileLogger{}
func (h *LogHTTPConfig) registerOutputSink() error {
logRoller := &lumberjack.Logger{ // newFileLogger returns registers zap sink and returns new fileLogger.
Filename: h.OutputPath, func newFileLogger(conf *LogHTTPConfig) (fileLogger, error) {
MaxSize: h.MaxLogSize, var flog = fileLogger{}
Compress: h.UseGzip, 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) { err := zap.RegisterSink(SinkName, func(_ *url.URL) (zap.Sink, error) {
return lumberjackSink{ return lumberjackSink{
Logger: logRoller, Logger: f.logRoller,
}, nil }, nil
}) })
if err != nil { if err != nil {
@ -57,6 +70,7 @@ func (h *LogHTTPConfig) registerOutputSink() error {
return nil return nil
} }
// Implementation of zap.Sink for using lumberjack.
type lumberjackSink struct { type lumberjackSink struct {
*lumberjack.Logger *lumberjack.Logger
} }
@ -65,10 +79,29 @@ func (lumberjackSink) Sync() error {
return nil 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. // LogHTTP logs http parameters from s3 request.
func LogHTTP(l *zap.Logger, config *LogHTTPConfig) Func { func LogHTTP(l *zap.Logger, config *LogHTTPConfig) Func {
fileLogger, err := config.getFileLogger() var err error
filelog, err = newFileLogger(config)
if err != nil { if err != nil {
l.Warn(logs.FailedToInitializeHTTPLogger)
return func(h http.Handler) http.Handler { return func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
h.ServeHTTP(w, r) h.ServeHTTP(w, r)
@ -81,7 +114,7 @@ func LogHTTP(l *zap.Logger, config *LogHTTPConfig) Func {
h.ServeHTTP(w, r) h.ServeHTTP(w, r)
return return
} }
var httplog = fileLogger.With( var httplog = filelog.With(
zap.String("from", r.RemoteAddr), zap.String("from", r.RemoteAddr),
zap.String("URI", r.RequestURI), zap.String("URI", r.RequestURI),
zap.String("method", r.Method), 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. // newLoggerConfig creates new zap.Config with disabled base fields.
func newLoggerConfig() zap.Config { func (*fileLogger) newLoggerConfig() zap.Config {
c := zap.NewProductionConfig() c := zap.NewProductionConfig()
c.DisableCaller = true c.DisableCaller = true
c.DisableStacktrace = true c.DisableStacktrace = true

View file

@ -26,6 +26,6 @@ func LogHTTP(l *zap.Logger, _ *LogHTTPConfig) Func {
} }
} }
func ReloadFileLogger(conf *LogHTTPConfig) error { func ReloadFileLogger(_ *LogHTTPConfig) error {
return nil return nil
} }

View file

@ -390,9 +390,9 @@ http_logging:
|----------------|--------|---------------|---------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |----------------|--------|---------------|---------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `enabled` | bool | yes | false | Flag to enable the logger. | | `enabled` | bool | yes | false | Flag to enable the logger. |
| `max_body` | int | yes | 1024 | Max body size for log output in bytes. | | `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. | | `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 | no | false | Whether to enable Gzip compression for backup log files. | | `gzip` | bool | yes | 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. | | `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 ### `cache` section

View file

@ -101,8 +101,10 @@ const (
FailedToResolveCID = "failed to resolve CID" // Debug in ../../api/middleware/metrics.go FailedToResolveCID = "failed to resolve CID" // Debug in ../../api/middleware/metrics.go
RequestStart = "request start" // Info in ../../api/middleware/reqinfo.go RequestStart = "request start" // Info in ../../api/middleware/reqinfo.go
RequestHTTP = "http request" // Info in ../../api/middleware/log_http.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 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 FailedToUnescapeObjectName = "failed to unescape object name" // Warn in ../../api/middleware/reqinfo.go
InvalidDefaultMaxAge = "invalid defaultMaxAge" // Fatal in ../../cmd/s3-gw/app_settings.go InvalidDefaultMaxAge = "invalid defaultMaxAge" // Fatal in ../../cmd/s3-gw/app_settings.go
CantShutDownService = "can't shut down service" // Panic in ../../cmd/s3-gw/service.go CantShutDownService = "can't shut down service" // Panic in ../../cmd/s3-gw/service.go