diff options
author | Francis Lavoie <[email protected]> | 2024-01-24 23:00:22 -0500 |
---|---|---|
committer | GitHub <[email protected]> | 2024-01-25 04:00:22 +0000 |
commit | b9c40e711115d35c2809313aeec42ab10fcd6914 (patch) | |
tree | 4c32d099733d2ec273589d85e2d4b21c2cd4e89c /modules/logging | |
parent | f5344f8caddee53cebe249712ba7803e22abf9f1 (diff) | |
download | caddy-b9c40e711115d35c2809313aeec42ab10fcd6914.tar.gz caddy-b9c40e711115d35c2809313aeec42ab10fcd6914.zip |
logging: Automatic `wrap` default for `filter` encoder (#5980)
Co-authored-by: Kévin Dunglas <[email protected]>
Diffstat (limited to 'modules/logging')
-rw-r--r-- | modules/logging/filterencoder.go | 66 |
1 files changed, 53 insertions, 13 deletions
diff --git a/modules/logging/filterencoder.go b/modules/logging/filterencoder.go index 735d7d424..9b1895d79 100644 --- a/modules/logging/filterencoder.go +++ b/modules/logging/filterencoder.go @@ -17,11 +17,13 @@ package logging import ( "encoding/json" "fmt" + "os" "time" "go.uber.org/zap" "go.uber.org/zap/buffer" "go.uber.org/zap/zapcore" + "golang.org/x/term" "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig" @@ -36,8 +38,10 @@ func init() { // log entries before they are actually encoded by // an underlying encoder. type FilterEncoder struct { - // The underlying encoder that actually - // encodes the log entries. Required. + // The underlying encoder that actually encodes the + // log entries. If not specified, defaults to "json", + // unless the output is a terminal, in which case + // it defaults to "console". WrappedRaw json.RawMessage `json:"wrap,omitempty" caddy:"namespace=caddy.logging.encoders inline_key=format"` // A map of field names to their filters. Note that this @@ -59,6 +63,9 @@ type FilterEncoder struct { // used to keep keys unique across nested objects keyPrefix string + + wrappedIsDefault bool + ctx caddy.Context } // CaddyModule returns the Caddy module information. @@ -71,16 +78,25 @@ func (FilterEncoder) CaddyModule() caddy.ModuleInfo { // Provision sets up the encoder. func (fe *FilterEncoder) Provision(ctx caddy.Context) error { - if fe.WrappedRaw == nil { - return fmt.Errorf("missing \"wrap\" (must specify an underlying encoder)") - } + fe.ctx = ctx - // set up wrapped encoder (required) - val, err := ctx.LoadModule(fe, "WrappedRaw") - if err != nil { - return fmt.Errorf("loading fallback encoder module: %v", err) + if fe.WrappedRaw == nil { + // if wrap is not specified, default to JSON + fe.wrapped = &JSONEncoder{} + if p, ok := fe.wrapped.(caddy.Provisioner); ok { + if err := p.Provision(ctx); err != nil { + return fmt.Errorf("provisioning fallback encoder module: %v", err) + } + } + fe.wrappedIsDefault = true + } else { + // set up wrapped encoder + val, err := ctx.LoadModule(fe, "WrappedRaw") + if err != nil { + return fmt.Errorf("loading fallback encoder module: %v", err) + } + fe.wrapped = val.(zapcore.Encoder) } - fe.wrapped = val.(zapcore.Encoder) // set up each field filter if fe.Fields == nil { @@ -97,6 +113,29 @@ func (fe *FilterEncoder) Provision(ctx caddy.Context) error { return nil } +// ConfigureDefaultFormat will set the default format to "console" +// if the writer is a terminal. If already configured as a filter +// encoder, it passes through the writer so a deeply nested filter +// encoder can configure its own default format. +func (fe *FilterEncoder) ConfigureDefaultFormat(wo caddy.WriterOpener) error { + if !fe.wrappedIsDefault { + if cfd, ok := fe.wrapped.(caddy.ConfiguresFormatterDefault); ok { + return cfd.ConfigureDefaultFormat(wo) + } + return nil + } + + if caddy.IsWriterStandardStream(wo) && term.IsTerminal(int(os.Stderr.Fd())) { + fe.wrapped = &ConsoleEncoder{} + if p, ok := fe.wrapped.(caddy.Provisioner); ok { + if err := p.Provision(fe.ctx); err != nil { + return fmt.Errorf("provisioning fallback encoder module: %v", err) + } + } + } + return nil +} + // UnmarshalCaddyfile sets up the module from Caddyfile tokens. Syntax: // // filter { @@ -390,7 +429,8 @@ func (mom logObjectMarshalerWrapper) MarshalLogObject(_ zapcore.ObjectEncoder) e // Interface guards var ( - _ zapcore.Encoder = (*FilterEncoder)(nil) - _ zapcore.ObjectMarshaler = (*logObjectMarshalerWrapper)(nil) - _ caddyfile.Unmarshaler = (*FilterEncoder)(nil) + _ zapcore.Encoder = (*FilterEncoder)(nil) + _ zapcore.ObjectMarshaler = (*logObjectMarshalerWrapper)(nil) + _ caddyfile.Unmarshaler = (*FilterEncoder)(nil) + _ caddy.ConfiguresFormatterDefault = (*FilterEncoder)(nil) ) |