summaryrefslogtreecommitdiffhomepage
path: root/modules/logging
diff options
context:
space:
mode:
authorFrancis Lavoie <[email protected]>2024-01-24 23:00:22 -0500
committerGitHub <[email protected]>2024-01-25 04:00:22 +0000
commitb9c40e711115d35c2809313aeec42ab10fcd6914 (patch)
tree4c32d099733d2ec273589d85e2d4b21c2cd4e89c /modules/logging
parentf5344f8caddee53cebe249712ba7803e22abf9f1 (diff)
downloadcaddy-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.go66
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)
)