[#369] Add response logging

Signed-off-by: Nikita Zinkevich <n.zinkevich@yadro.com>
This commit is contained in:
Nikita Zinkevich 2024-07-24 11:38:32 +03:00
parent 99e0af1cd0
commit 6f87a9b3b6
6 changed files with 49 additions and 15 deletions

View file

@ -22,6 +22,7 @@ type LogHTTPConfig struct {
MaxLogSize int
OutputPath string
UseGzip bool
LogResponse bool
}
type fileLogger struct {
@ -97,6 +98,23 @@ func ReloadFileLogger(conf *LogHTTPConfig) error {
return nil
}
// responseReadWriter helps read http response body.
type responseReadWriter struct {
http.ResponseWriter
response *bytes.Buffer
}
func (ww *responseReadWriter) Write(data []byte) (int, error) {
ww.response.Write(data)
return ww.ResponseWriter.Write(data)
}
func (ww *responseReadWriter) Flush() {
if f, ok := ww.ResponseWriter.(http.Flusher); ok {
f.Flush()
}
}
// LogHTTP logs http parameters from s3 request.
func LogHTTP(l *zap.Logger, config *LogHTTPConfig) Func {
var err error
@ -129,8 +147,18 @@ func LogHTTP(l *zap.Logger, config *LogHTTPConfig) Func {
l.Warn(logs.FailedToGetRequestBody, zap.Error(err))
}
}
httplog.Info(logs.RequestHTTP)
if !config.LogResponse {
httplog.Info(logs.LogHTTP)
h.ServeHTTP(w, r)
} else {
var resp = bytes.Buffer{}
ww := &responseReadWriter{ResponseWriter: w, response: &resp}
h.ServeHTTP(ww, r)
if int64(resp.Len()) <= config.MaxBody {
httplog.With(zap.String("response", base64.StdEncoding.EncodeToString(resp.Bytes()))).
Info(logs.LogHTTP)
}
}
})
}
}

View file

@ -15,6 +15,7 @@ type LogHTTPConfig struct {
MaxLogSize int
OutputPath string
UseGzip bool
LogResponse bool
}
func LogHTTP(l *zap.Logger, _ *LogHTTPConfig) Func {

View file

@ -597,6 +597,7 @@ func (s *appSettings) updateHTTPLoggingSettings(cfg *viper.Viper, log *zap.Logge
s.httpLogging.MaxLogSize = cfg.GetInt(cfgHTTPLoggingMaxLogSize)
s.httpLogging.OutputPath = cfg.GetString(cfgHTTPLoggingDestination)
s.httpLogging.UseGzip = cfg.GetBool(cfgHTTPLoggingGzip)
s.httpLogging.LogResponse = cfg.GetBool(cfgHTTPLoggingLogResponse)
if err := s3middleware.ReloadFileLogger(s.httpLogging); err != nil {
log.Error(logs.FailedToReloadHTTPFileLogger, zap.Error(err))
}

View file

@ -87,6 +87,7 @@ const ( // Settings.
cfgHTTPLoggingMaxLogSize = "http_logging.max_log_size"
cfgHTTPLoggingDestination = "http_logging.destination"
cfgHTTPLoggingGzip = "http_logging.gzip"
cfgHTTPLoggingLogResponse = "http_logging.log_response"
// Wallet.
cfgWalletPath = "wallet.path"
@ -792,6 +793,7 @@ func newSettings() *viper.Viper {
v.SetDefault(cfgHTTPLoggingMaxLogSize, 50)
v.SetDefault(cfgHTTPLoggingDestination, "stdout")
v.SetDefault(cfgHTTPLoggingGzip, false)
v.SetDefault(cfgHTTPLoggingLogResponse, true)
// pool:
v.SetDefault(cfgPoolErrorThreshold, defaultPoolErrorThreshold)

View file

@ -387,6 +387,7 @@ http_logging:
max_log_size: 20
gzip: true
destination: stdout
log_response: true
```
| Parameter | Type | SIGHUP reload | Default value | Description |
@ -394,8 +395,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 | 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. |
| `gzip` | bool | yes | false | Whether to enable Gzip compression to 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. File and folders are created if necessary. |
| `log_response` | bool | yes | true | Whether to attach response body to the log. |
### `cache` section

View file

@ -99,7 +99,7 @@ const (
FailedToPassAuthentication = "failed to pass authentication" // Error in ../../api/middleware/auth.go
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
LogHTTP = "http log" // 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