Compare commits
4 commits
master
...
feature/lo
Author | SHA1 | Date | |
---|---|---|---|
2bfeeca024 | |||
6ae42c699c | |||
6f3bedc023 | |||
8e2a927334 |
13 changed files with 299 additions and 0 deletions
|
@ -106,3 +106,9 @@ const (
|
||||||
PartNumberQuery = "partNumber"
|
PartNumberQuery = "partNumber"
|
||||||
LegalHoldQuery = "legal-hold"
|
LegalHoldQuery = "legal-hold"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
StdoutPath = "stdout"
|
||||||
|
StderrPath = "stderr"
|
||||||
|
SinkName = "lumberjack"
|
||||||
|
)
|
||||||
|
|
170
api/middleware/log_http.go
Normal file
170
api/middleware/log_http.go
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
//go:build loghttp
|
||||||
|
|
||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"go.uber.org/zap/zapcore"
|
||||||
|
"gopkg.in/natefinch/lumberjack.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LogHTTPConfig struct {
|
||||||
|
Enabled bool
|
||||||
|
MaxBody int64
|
||||||
|
MaxLogSize int
|
||||||
|
OutputPath string
|
||||||
|
UseGzip bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type fileLogger struct {
|
||||||
|
*zap.Logger
|
||||||
|
logRoller *lumberjack.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
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: f.logRoller,
|
||||||
|
}, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implementation of zap.Sink for using lumberjack.
|
||||||
|
type lumberjackSink struct {
|
||||||
|
*lumberjack.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return func(h http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if !config.Enabled {
|
||||||
|
h.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var httplog = filelog.With(
|
||||||
|
zap.String("from", r.RemoteAddr),
|
||||||
|
zap.String("URI", r.RequestURI),
|
||||||
|
zap.String("method", r.Method),
|
||||||
|
)
|
||||||
|
|
||||||
|
httplog = withFieldIfExist(httplog, "query", r.URL.Query())
|
||||||
|
httplog = withFieldIfExist(httplog, "headers", r.Header)
|
||||||
|
if r.ContentLength > 0 && r.ContentLength <= config.MaxBody {
|
||||||
|
httplog, err = withBody(httplog, r)
|
||||||
|
if err != nil {
|
||||||
|
l.Warn(logs.FailedToGetRequestBody, zap.Error(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
httplog.Info(logs.RequestHTTP)
|
||||||
|
h.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// newLoggerConfig creates new zap.Config with disabled base fields.
|
||||||
|
func (*fileLogger) newLoggerConfig() zap.Config {
|
||||||
|
c := zap.NewProductionConfig()
|
||||||
|
c.DisableCaller = true
|
||||||
|
c.DisableStacktrace = true
|
||||||
|
c.EncoderConfig.MessageKey = zapcore.OmitKey
|
||||||
|
c.EncoderConfig.LevelKey = zapcore.OmitKey
|
||||||
|
c.EncoderConfig.TimeKey = zapcore.OmitKey
|
||||||
|
c.EncoderConfig.FunctionKey = zapcore.OmitKey
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// withBody reads body and attach it to log output.
|
||||||
|
func withBody(httplog *zap.Logger, r *http.Request) (*zap.Logger, error) {
|
||||||
|
body, err := io.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("read body error: %w", err)
|
||||||
|
}
|
||||||
|
defer r.Body.Close()
|
||||||
|
r.Body = io.NopCloser(bytes.NewBuffer(body))
|
||||||
|
|
||||||
|
httplog = httplog.With(zap.String("body", string(body)))
|
||||||
|
|
||||||
|
return httplog, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// withFieldIfExist checks whether data is not empty and attach it to log output.
|
||||||
|
func withFieldIfExist(log *zap.Logger, label string, data map[string][]string) *zap.Logger {
|
||||||
|
if len(data) != 0 {
|
||||||
|
log = log.With(zap.Any(label, data))
|
||||||
|
}
|
||||||
|
return log
|
||||||
|
}
|
31
api/middleware/log_http_stub.go
Normal file
31
api/middleware/log_http_stub.go
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
//go:build !loghttp
|
||||||
|
|
||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LogHTTPConfig struct {
|
||||||
|
Enabled bool
|
||||||
|
MaxBody int64
|
||||||
|
MaxLogSize int
|
||||||
|
OutputPath string
|
||||||
|
UseGzip bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func LogHTTP(l *zap.Logger, _ *LogHTTPConfig) Func {
|
||||||
|
l.Warn(logs.LogHTTPDisabledInThisBuild)
|
||||||
|
return func(h http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
h.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReloadFileLogger(_ *LogHTTPConfig) error {
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -109,6 +109,7 @@ type Config struct {
|
||||||
Handler Handler
|
Handler Handler
|
||||||
Center s3middleware.Center
|
Center s3middleware.Center
|
||||||
Log *zap.Logger
|
Log *zap.Logger
|
||||||
|
LogHTTP *s3middleware.LogHTTPConfig
|
||||||
Metrics *metrics.AppMetrics
|
Metrics *metrics.AppMetrics
|
||||||
|
|
||||||
MiddlewareSettings Settings
|
MiddlewareSettings Settings
|
||||||
|
@ -128,6 +129,11 @@ type Config struct {
|
||||||
|
|
||||||
func NewRouter(cfg Config) *chi.Mux {
|
func NewRouter(cfg Config) *chi.Mux {
|
||||||
api := chi.NewRouter()
|
api := chi.NewRouter()
|
||||||
|
|
||||||
|
if cfg.LogHTTP.Enabled {
|
||||||
|
api.Use(s3middleware.LogHTTP(cfg.Log, cfg.LogHTTP))
|
||||||
|
}
|
||||||
|
|
||||||
api.Use(
|
api.Use(
|
||||||
s3middleware.Request(cfg.Log, cfg.MiddlewareSettings),
|
s3middleware.Request(cfg.Log, cfg.MiddlewareSettings),
|
||||||
middleware.ThrottleWithOpts(cfg.Throttle),
|
middleware.ThrottleWithOpts(cfg.Throttle),
|
||||||
|
|
|
@ -75,6 +75,7 @@ func prepareRouter(t *testing.T, opts ...option) *routerMock {
|
||||||
Handler: handlerTestMock,
|
Handler: handlerTestMock,
|
||||||
Center: ¢erMock{t: t},
|
Center: ¢erMock{t: t},
|
||||||
Log: logger,
|
Log: logger,
|
||||||
|
LogHTTP: new(s3middleware.LogHTTPConfig),
|
||||||
Metrics: metrics.NewAppMetrics(metricsConfig),
|
Metrics: metrics.NewAppMetrics(metricsConfig),
|
||||||
MiddlewareSettings: middlewareSettings,
|
MiddlewareSettings: middlewareSettings,
|
||||||
PolicyChecker: policyChecker,
|
PolicyChecker: policyChecker,
|
||||||
|
|
|
@ -83,6 +83,7 @@ type (
|
||||||
|
|
||||||
appSettings struct {
|
appSettings struct {
|
||||||
logLevel zap.AtomicLevel
|
logLevel zap.AtomicLevel
|
||||||
|
httpLogging *s3middleware.LogHTTPConfig
|
||||||
maxClient maxClientsConfig
|
maxClient maxClientsConfig
|
||||||
defaultMaxAge int
|
defaultMaxAge int
|
||||||
reconnectInterval time.Duration
|
reconnectInterval time.Duration
|
||||||
|
@ -189,6 +190,7 @@ func (a *App) initLayer() {
|
||||||
func newAppSettings(log *Logger, v *viper.Viper) *appSettings {
|
func newAppSettings(log *Logger, v *viper.Viper) *appSettings {
|
||||||
settings := &appSettings{
|
settings := &appSettings{
|
||||||
logLevel: log.lvl,
|
logLevel: log.lvl,
|
||||||
|
httpLogging: new(s3middleware.LogHTTPConfig),
|
||||||
maxClient: newMaxClients(v),
|
maxClient: newMaxClients(v),
|
||||||
defaultMaxAge: fetchDefaultMaxAge(v, log.logger),
|
defaultMaxAge: fetchDefaultMaxAge(v, log.logger),
|
||||||
reconnectInterval: fetchReconnectInterval(v),
|
reconnectInterval: fetchReconnectInterval(v),
|
||||||
|
@ -218,6 +220,7 @@ func (s *appSettings) update(v *viper.Viper, log *zap.Logger) {
|
||||||
s.setRetryMaxAttempts(fetchRetryMaxAttempts(v))
|
s.setRetryMaxAttempts(fetchRetryMaxAttempts(v))
|
||||||
s.setRetryMaxBackoff(fetchRetryMaxBackoff(v))
|
s.setRetryMaxBackoff(fetchRetryMaxBackoff(v))
|
||||||
s.setRetryStrategy(fetchRetryStrategy(v))
|
s.setRetryStrategy(fetchRetryStrategy(v))
|
||||||
|
s.updateHTTPLoggingSettings(v, log)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *appSettings) updateNamespacesSettings(v *viper.Viper, log *zap.Logger) {
|
func (s *appSettings) updateNamespacesSettings(v *viper.Viper, log *zap.Logger) {
|
||||||
|
@ -561,6 +564,20 @@ func newMaxClients(cfg *viper.Viper) maxClientsConfig {
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *appSettings) updateHTTPLoggingSettings(cfg *viper.Viper, log *zap.Logger) {
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
|
||||||
|
s.httpLogging.Enabled = cfg.GetBool(cfgHTTPLoggingEnabled)
|
||||||
|
s.httpLogging.MaxBody = cfg.GetInt64(cfgHTTPLoggingMaxBody)
|
||||||
|
s.httpLogging.MaxLogSize = cfg.GetInt(cfgHTTPLoggingMaxLogSize)
|
||||||
|
s.httpLogging.OutputPath = cfg.GetString(cfgHTTPLoggingDestination)
|
||||||
|
s.httpLogging.UseGzip = cfg.GetBool(cfgHTTPLoggingGzip)
|
||||||
|
if err := s3middleware.ReloadFileLogger(s.httpLogging); err != nil {
|
||||||
|
log.Error(logs.FailedToReloadHTTPFileLogger, zap.Error(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func getPools(ctx context.Context, logger *zap.Logger, cfg *viper.Viper) (*pool.Pool, *treepool.Pool, *keys.PrivateKey) {
|
func getPools(ctx context.Context, logger *zap.Logger, cfg *viper.Viper) (*pool.Pool, *treepool.Pool, *keys.PrivateKey) {
|
||||||
var prm pool.InitParameters
|
var prm pool.InitParameters
|
||||||
var prmTree treepool.InitParameters
|
var prmTree treepool.InitParameters
|
||||||
|
@ -682,6 +699,7 @@ func (a *App) Serve(ctx context.Context) {
|
||||||
Handler: a.api,
|
Handler: a.api,
|
||||||
Center: a.ctr,
|
Center: a.ctr,
|
||||||
Log: a.log,
|
Log: a.log,
|
||||||
|
LogHTTP: a.settings.httpLogging,
|
||||||
Metrics: a.metrics,
|
Metrics: a.metrics,
|
||||||
Domains: domains,
|
Domains: domains,
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,13 @@ const ( // Settings.
|
||||||
cfgLoggerLevel = "logger.level"
|
cfgLoggerLevel = "logger.level"
|
||||||
cfgLoggerDestination = "logger.destination"
|
cfgLoggerDestination = "logger.destination"
|
||||||
|
|
||||||
|
// HttpLogging.
|
||||||
|
cfgHTTPLoggingEnabled = "http_logging.enabled"
|
||||||
|
cfgHTTPLoggingMaxBody = "http_logging.max_body"
|
||||||
|
cfgHTTPLoggingMaxLogSize = "http_logging.max_log_size"
|
||||||
|
cfgHTTPLoggingDestination = "http_logging.destination"
|
||||||
|
cfgHTTPLoggingGzip = "http_logging.gzip"
|
||||||
|
|
||||||
// Wallet.
|
// Wallet.
|
||||||
cfgWalletPath = "wallet.path"
|
cfgWalletPath = "wallet.path"
|
||||||
cfgWalletAddress = "wallet.address"
|
cfgWalletAddress = "wallet.address"
|
||||||
|
@ -715,6 +722,13 @@ func newSettings() *viper.Viper {
|
||||||
v.SetDefault(cfgLoggerLevel, "debug")
|
v.SetDefault(cfgLoggerLevel, "debug")
|
||||||
v.SetDefault(cfgLoggerDestination, "stdout")
|
v.SetDefault(cfgLoggerDestination, "stdout")
|
||||||
|
|
||||||
|
// http logger
|
||||||
|
v.SetDefault(cfgHTTPLoggingEnabled, false)
|
||||||
|
v.SetDefault(cfgHTTPLoggingMaxBody, 1024)
|
||||||
|
v.SetDefault(cfgHTTPLoggingMaxLogSize, 50)
|
||||||
|
v.SetDefault(cfgHTTPLoggingDestination, "stdout")
|
||||||
|
v.SetDefault(cfgHTTPLoggingGzip, false)
|
||||||
|
|
||||||
// pool:
|
// pool:
|
||||||
v.SetDefault(cfgPoolErrorThreshold, defaultPoolErrorThreshold)
|
v.SetDefault(cfgPoolErrorThreshold, defaultPoolErrorThreshold)
|
||||||
v.SetDefault(cfgStreamTimeout, defaultStreamTimeout)
|
v.SetDefault(cfgStreamTimeout, defaultStreamTimeout)
|
||||||
|
|
|
@ -45,6 +45,17 @@ S3_GW_CONFIG=/path/to/config/yaml
|
||||||
# Logger
|
# Logger
|
||||||
S3_GW_LOGGER_LEVEL=debug
|
S3_GW_LOGGER_LEVEL=debug
|
||||||
|
|
||||||
|
# HTTP logger
|
||||||
|
S3_GW_HTTP_LOGGING_ENABLED=false
|
||||||
|
# max body size to log
|
||||||
|
S3_GW_HTTP_LOGGING_MAX_BODY=1024
|
||||||
|
# max log size in Mb
|
||||||
|
S3_GW_HTTP_LOGGING_MAX_LOG_SIZE: 20
|
||||||
|
# use log compression
|
||||||
|
S3_GW_HTTP_LOGGING_GZIP=true
|
||||||
|
# possible destination output values: filesystem path, url, "stdout", "stderr"
|
||||||
|
S3_GW_HTTP_LOGGING_DESTINATION=stdout
|
||||||
|
|
||||||
# RPC endpoint and order of resolving of bucket names
|
# RPC endpoint and order of resolving of bucket names
|
||||||
S3_GW_RPC_ENDPOINT=http://morph-chain.frostfs.devenv:30333/
|
S3_GW_RPC_ENDPOINT=http://morph-chain.frostfs.devenv:30333/
|
||||||
S3_GW_RESOLVE_ORDER="nns dns"
|
S3_GW_RESOLVE_ORDER="nns dns"
|
||||||
|
|
|
@ -47,6 +47,18 @@ logger:
|
||||||
level: debug
|
level: debug
|
||||||
destination: stdout
|
destination: stdout
|
||||||
|
|
||||||
|
# log http request data (URI, headers, query, etc)
|
||||||
|
http_logging:
|
||||||
|
enabled: false
|
||||||
|
# max body size to log
|
||||||
|
max_body: 1024
|
||||||
|
# max log size in Mb
|
||||||
|
max_log_size: 20
|
||||||
|
# use log compression
|
||||||
|
gzip: true
|
||||||
|
# possible output values: filesystem path, url, "stdout", "stderr"
|
||||||
|
destination: stdout
|
||||||
|
|
||||||
# RPC endpoint and order of resolving of bucket names
|
# RPC endpoint and order of resolving of bucket names
|
||||||
rpc_endpoint: http://morph-chain.frostfs.devenv:30333
|
rpc_endpoint: http://morph-chain.frostfs.devenv:30333
|
||||||
resolve_order:
|
resolve_order:
|
||||||
|
|
|
@ -176,6 +176,7 @@ There are some custom types used for brevity:
|
||||||
| `placement_policy` | [Placement policy configuration](#placement_policy-section) |
|
| `placement_policy` | [Placement policy configuration](#placement_policy-section) |
|
||||||
| `server` | [Server configuration](#server-section) |
|
| `server` | [Server configuration](#server-section) |
|
||||||
| `logger` | [Logger configuration](#logger-section) |
|
| `logger` | [Logger configuration](#logger-section) |
|
||||||
|
| `http_logging` | [HTTP Request logger configuration](#http_logging-section) |
|
||||||
| `cache` | [Cache configuration](#cache-section) |
|
| `cache` | [Cache configuration](#cache-section) |
|
||||||
| `cors` | [CORS configuration](#cors-section) |
|
| `cors` | [CORS configuration](#cors-section) |
|
||||||
| `pprof` | [Pprof configuration](#pprof-section) |
|
| `pprof` | [Pprof configuration](#pprof-section) |
|
||||||
|
@ -373,6 +374,27 @@ logger:
|
||||||
| `level` | `string` | yes | `debug` | Logging level.<br/>Possible values: `debug`, `info`, `warn`, `error`, `dpanic`, `panic`, `fatal`. |
|
| `level` | `string` | yes | `debug` | Logging level.<br/>Possible values: `debug`, `info`, `warn`, `error`, `dpanic`, `panic`, `fatal`. |
|
||||||
| `destination` | `string` | no | `stdout` | Destination for logger: `stdout` or `journald` |
|
| `destination` | `string` | no | `stdout` | Destination for logger: `stdout` or `journald` |
|
||||||
|
|
||||||
|
|
||||||
|
### `http_logging` section
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
http_logging:
|
||||||
|
enabled: false
|
||||||
|
max_body: 1024
|
||||||
|
max_log_size: 20
|
||||||
|
gzip: true
|
||||||
|
destination: stdout
|
||||||
|
```
|
||||||
|
|
||||||
|
| Parameter | Type | SIGHUP reload | Default value | Description |
|
||||||
|
|----------------|--------|---------------|---------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| `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. |
|
||||||
|
|
||||||
|
|
||||||
### `cache` section
|
### `cache` section
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -34,6 +34,7 @@ require (
|
||||||
golang.org/x/text v0.14.0
|
golang.org/x/text v0.14.0
|
||||||
google.golang.org/grpc v1.59.0
|
google.golang.org/grpc v1.59.0
|
||||||
google.golang.org/protobuf v1.33.0
|
google.golang.org/protobuf v1.33.0
|
||||||
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -696,6 +696,8 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||||
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
|
|
@ -100,6 +100,11 @@ const (
|
||||||
FailedToPassAuthentication = "failed to pass authentication" // Error in ../../api/middleware/auth.go
|
FailedToPassAuthentication = "failed to pass authentication" // Error in ../../api/middleware/auth.go
|
||||||
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
|
||||||
|
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
|
||||||
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
|
||||||
|
|
Loading…
Reference in a new issue