Go API Documentation

github.com/caddyserver/caddy/v2/modules/logging

No package summary is available.

  1. Package
    1. Constants
    2. Vars
    3. Types
    4. Functions
    5. Private functions
  2. Tests

Package

Files: 8. Third party imports: 6. Imports from organisation: 0. Tests: 0. Benchmarks: 0.

Constants

const (
	// Replace value(s).
	replaceAction	filterAction	= "replace"

	// Hash value(s).
	hashAction	filterAction	= "hash"

	// Delete.
	deleteAction	filterAction	= "delete"
)

Vars

var (
	_	zapcore.Encoder				= (*AppendEncoder)(nil)
	_	caddyfile.Unmarshaler			= (*AppendEncoder)(nil)
	_	caddy.ConfiguresFormatterDefault	= (*AppendEncoder)(nil)
)
var bufferpool = buffer.NewPool()

Types

AppendEncoder

AppendEncoder can be used to add fields to all log entries that pass through it. It is a wrapper around another encoder, which it uses to actually encode the log entries. It is most useful for adding information about the Caddy instance that is producing the log entries, possibly via an environment variable.

type AppendEncoder struct {
	// 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 values. The values
	// can be global placeholders (e.g. env vars), or constants.
	// Note that the encoder does not run as part of an HTTP
	// request context, so request placeholders are not available.
	Fields	map[string]any	`json:"fields,omitempty"`

	wrapped	zapcore.Encoder
	repl	*caddy.Replacer

	wrappedIsDefault	bool
	ctx			caddy.Context
}

ConsoleEncoder

ConsoleEncoder encodes log entries that are mostly human-readable.

type ConsoleEncoder struct {
	zapcore.Encoder	`json:"-"`
	LogEncoderConfig
}

CookieFilter

CookieFilter is a Caddy log field filter that filters cookies.

This filter updates the logged HTTP header string to remove, replace or hash cookies containing sensitive data. For instance, it can be used to redact any kind of secrets, such as session IDs.

If several actions are configured for the same cookie name, only the first will be applied.

type CookieFilter struct {
	// A list of actions to apply to the cookies.
	Actions []cookieFilterAction `json:"actions"`
}

DeleteFilter

DeleteFilter is a Caddy log field filter that deletes the field.

type DeleteFilter struct{}

FileWriter

FileWriter can write logs to files. By default, log files are rotated ("rolled") when they get large, and old log files get deleted, to ensure that the process does not exhaust disk space.

type FileWriter struct {
	// Filename is the name of the file to write.
	Filename	string	`json:"filename,omitempty"`

	// The file permissions mode.
	// 0600 by default.
	Mode	fileMode	`json:"mode,omitempty"`

	// Roll toggles log rolling or rotation, which is
	// enabled by default.
	Roll	*bool	`json:"roll,omitempty"`

	// When a log file reaches approximately this size,
	// it will be rotated.
	RollSizeMB	int	`json:"roll_size_mb,omitempty"`

	// Whether to compress rolled files. Default: true
	RollCompress	*bool	`json:"roll_gzip,omitempty"`

	// Whether to use local timestamps in rolled filenames.
	// Default: false
	RollLocalTime	bool	`json:"roll_local_time,omitempty"`

	// The maximum number of rolled log files to keep.
	// Default: 10
	RollKeep	int	`json:"roll_keep,omitempty"`

	// How many days to keep rolled log files. Default: 90
	RollKeepDays	int	`json:"roll_keep_days,omitempty"`
}

FilterEncoder

FilterEncoder can filter (manipulate) fields on log entries before they are actually encoded by an underlying encoder.

type FilterEncoder struct {
	// 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
	// is not a module map; the keys are field names.
	//
	// Nested fields can be referenced by representing a
	// layer of nesting with `>`. In other words, for an
	// object like `{"a":{"b":0}}`, the inner field can
	// be referenced as `a>b`.
	//
	// The following fields are fundamental to the log and
	// cannot be filtered because they are added by the
	// underlying logging library as special cases: ts,
	// level, logger, and msg.
	FieldsRaw	map[string]json.RawMessage	`json:"fields,omitempty" caddy:"namespace=caddy.logging.encoders.filter inline_key=filter"`

	wrapped	zapcore.Encoder
	Fields	map[string]LogFieldFilter	`json:"-"`

	// used to keep keys unique across nested objects
	keyPrefix	string

	wrappedIsDefault	bool
	ctx			caddy.Context
}

HashFilter

HashFilter is a Caddy log field filter that replaces the field with the initial 4 bytes of the SHA-256 hash of the content. Operates on string fields, or on arrays of strings where each string is hashed.

type HashFilter struct{}

IPMaskFilter

IPMaskFilter is a Caddy log field filter that masks IP addresses in a string, or in an array of strings. The string may be a comma separated list of IP addresses, where all of the values will be masked.

type IPMaskFilter struct {
	// The IPv4 mask, as an subnet size CIDR.
	IPv4MaskRaw	int	`json:"ipv4_cidr,omitempty"`

	// The IPv6 mask, as an subnet size CIDR.
	IPv6MaskRaw	int	`json:"ipv6_cidr,omitempty"`

	v4Mask	net.IPMask
	v6Mask	net.IPMask
}

JSONEncoder

JSONEncoder encodes entries as JSON.

type JSONEncoder struct {
	zapcore.Encoder	`json:"-"`
	LogEncoderConfig
}

LogEncoderConfig

LogEncoderConfig holds configuration common to most encoders.

type LogEncoderConfig struct {
	MessageKey	*string	`json:"message_key,omitempty"`
	LevelKey	*string	`json:"level_key,omitempty"`
	TimeKey		*string	`json:"time_key,omitempty"`
	NameKey		*string	`json:"name_key,omitempty"`
	CallerKey	*string	`json:"caller_key,omitempty"`
	StacktraceKey	*string	`json:"stacktrace_key,omitempty"`
	LineEnding	*string	`json:"line_ending,omitempty"`

	// Recognized values are: unix_seconds_float, unix_milli_float, unix_nano, iso8601, rfc3339, rfc3339_nano, wall, wall_milli, wall_nano, common_log.
	// The value may also be custom format per the Go `time` package layout specification, as described [here](https://pkg.go.dev/time#pkg-constants).
	TimeFormat	string	`json:"time_format,omitempty"`
	TimeLocal	bool	`json:"time_local,omitempty"`

	// Recognized values are: s/second/seconds, ns/nano/nanos, ms/milli/millis, string.
	// Empty and unrecognized value default to seconds.
	DurationFormat	string	`json:"duration_format,omitempty"`

	// Recognized values are: lower, upper, color.
	// Empty and unrecognized value default to lower.
	LevelFormat	string	`json:"level_format,omitempty"`
}

LogFieldFilter

LogFieldFilter can filter (or manipulate) a field in a log entry.

type LogFieldFilter interface {
	Filter(zapcore.Field) zapcore.Field
}

MockCore

MockCore is a no-op module, purely for testing

type MockCore struct {
	zapcore.Core `json:"-"`
}

NetWriter

NetWriter implements a log writer that outputs to a network socket. If the socket goes down, it will dump logs to stderr while it attempts to reconnect.

type NetWriter struct {
	// The address of the network socket to which to connect.
	Address	string	`json:"address,omitempty"`

	// The timeout to wait while connecting to the socket.
	DialTimeout	caddy.Duration	`json:"dial_timeout,omitempty"`

	// If enabled, allow connections errors when first opening the
	// writer. The error and subsequent log entries will be reported
	// to stderr instead until a connection can be re-established.
	SoftStart	bool	`json:"soft_start,omitempty"`

	addr	caddy.NetworkAddress
}

QueryFilter

QueryFilter is a Caddy log field filter that filters query parameters from a URL.

This filter updates the logged URL string to remove, replace or hash query parameters containing sensitive data. For instance, it can be used to redact any kind of secrets which were passed as query parameters, such as OAuth access tokens, session IDs, magic link tokens, etc.

type QueryFilter struct {
	// A list of actions to apply to the query parameters of the URL.
	Actions []queryFilterAction `json:"actions"`
}

RegexpFilter

RegexpFilter is a Caddy log field filter that replaces the field matching the provided regexp with the indicated string. If the field is an array of strings, each of them will have the regexp replacement applied.

type RegexpFilter struct {
	// The regular expression pattern defining what to replace.
	RawRegexp	string	`json:"regexp,omitempty"`

	// The value to use as replacement
	Value	string	`json:"value,omitempty"`

	regexp	*regexp.Regexp
}

RenameFilter

RenameFilter is a Caddy log field filter that renames the field's key with the indicated name.

type RenameFilter struct {
	Name string `json:"name,omitempty"`
}

ReplaceFilter

ReplaceFilter is a Caddy log field filter that replaces the field with the indicated string.

type ReplaceFilter struct {
	Value string `json:"value,omitempty"`
}

cookieFilterAction

This type doesn't have documentation.

type cookieFilterAction struct {
	// `replace` to replace the value of the cookie, `hash` to replace it with the 4 initial bytes of the SHA-256 of its content or `delete` to remove it entirely.
	Type	filterAction	`json:"type"`

	// The name of the cookie.
	Name	string	`json:"name"`

	// The value to use as replacement if the action is `replace`.
	Value	string	`json:"value,omitempty"`
}

fileMode

fileMode is a string made of 1 to 4 octal digits representing a numeric mode as specified with the chmod unix command. "0777" and "777" are thus equivalent values.

type fileMode os.FileMode

filterAction

This type doesn't have documentation.

type filterAction string

logObjectMarshalerWrapper

logObjectMarshalerWrapper allows us to recursively filter fields of objects as they get encoded.

type logObjectMarshalerWrapper struct {
	enc	FilterEncoder
	marsh	zapcore.ObjectMarshaler
}

nopEncoder

nopEncoder is a zapcore.Encoder that does nothing.

type nopEncoder struct{}

queryFilterAction

This type doesn't have documentation.

type queryFilterAction struct {
	// `replace` to replace the value(s) associated with the parameter(s), `hash` to replace them with the 4 initial bytes of the SHA-256 of their content or `delete` to remove them entirely.
	Type	filterAction	`json:"type"`

	// The name of the query parameter.
	Parameter	string	`json:"parameter"`

	// The value to use as replacement if the action is `replace`.
	Value	string	`json:"value,omitempty"`
}

redialerConn

redialerConn wraps an underlying Conn so that if any writes fail, the connection is redialed and the write is retried.

type redialerConn struct {
	net.Conn
	connMu		sync.RWMutex
	nw		NetWriter
	timeout		time.Duration
	lastRedial	time.Time
}

Functions

func (*AppendEncoder) ConfigureDefaultFormat

ConfigureDefaultFormat will set the default format to "console" if the writer is a terminal. If already configured, it passes through the writer so a deeply nested encoder can configure its own default format.

func (fe *AppendEncoder) 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
}

Cognitive complexity: 11, Cyclomatic complexity: 7

Uses: fmt.Errorf, os.Stderr, term.IsTerminal.

func (*AppendEncoder) Provision

Provision sets up the encoder.

func (fe *AppendEncoder) Provision(ctx caddy.Context) error {
	fe.ctx = ctx
	fe.repl = caddy.NewReplacer()

	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)
	}

	return nil
}

Cognitive complexity: 11, Cyclomatic complexity: 5

Uses: fmt.Errorf, zapcore.Encoder.

func (*AppendEncoder) UnmarshalCaddyfile

UnmarshalCaddyfile sets up the module from Caddyfile tokens. Syntax:

append {
    wrap <another encoder>
    fields {
        <field> <value>
    }
    <field> <value>
}

func (fe *AppendEncoder) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
	d.Next()	// consume encoder name

	// parse a field
	parseField := func() error {
		if fe.Fields == nil {
			fe.Fields = make(map[string]any)
		}
		field := d.Val()
		if !d.NextArg() {
			return d.ArgErr()
		}
		fe.Fields[field] = d.ScalarVal()
		if d.NextArg() {
			return d.ArgErr()
		}
		return nil
	}

	for d.NextBlock(0) {
		switch d.Val() {
		case "wrap":
			if !d.NextArg() {
				return d.ArgErr()
			}
			moduleName := d.Val()
			moduleID := "caddy.logging.encoders." + moduleName
			unm, err := caddyfile.UnmarshalModule(d, moduleID)
			if err != nil {
				return err
			}
			enc, ok := unm.(zapcore.Encoder)
			if !ok {
				return d.Errf("module %s (%T) is not a zapcore.Encoder", moduleID, unm)
			}
			fe.WrappedRaw = caddyconfig.JSONModuleObject(enc, "format", moduleName, nil)

		case "fields":
			for nesting := d.Nesting(); d.NextBlock(nesting); {
				err := parseField()
				if err != nil {
					return err
				}
			}

		default:
			// if unknown, assume it's a field so that
			// the config can be flat
			err := parseField()
			if err != nil {
				return err
			}
		}
	}
	return nil
}

Cognitive complexity: 25, Cyclomatic complexity: 14

Uses: caddyconfig.JSONModuleObject, caddyfile.UnmarshalModule, zapcore.Encoder.

func (*LogEncoderConfig) ZapcoreEncoderConfig

ZapcoreEncoderConfig returns the equivalent zapcore.EncoderConfig. If lec is nil, zap.NewProductionEncoderConfig() is returned.

func (lec *LogEncoderConfig) ZapcoreEncoderConfig() zapcore.EncoderConfig {
	cfg := zap.NewProductionEncoderConfig()
	if lec == nil {
		lec = new(LogEncoderConfig)
	}
	if lec.MessageKey != nil {
		cfg.MessageKey = *lec.MessageKey
	}
	if lec.LevelKey != nil {
		cfg.LevelKey = *lec.LevelKey
	}
	if lec.TimeKey != nil {
		cfg.TimeKey = *lec.TimeKey
	}
	if lec.NameKey != nil {
		cfg.NameKey = *lec.NameKey
	}
	if lec.CallerKey != nil {
		cfg.CallerKey = *lec.CallerKey
	}
	if lec.StacktraceKey != nil {
		cfg.StacktraceKey = *lec.StacktraceKey
	}
	if lec.LineEnding != nil {
		cfg.LineEnding = *lec.LineEnding
	}

	// time format
	var timeFormatter zapcore.TimeEncoder
	switch lec.TimeFormat {
	case "", "unix_seconds_float":
		timeFormatter = zapcore.EpochTimeEncoder
	case "unix_milli_float":
		timeFormatter = zapcore.EpochMillisTimeEncoder
	case "unix_nano":
		timeFormatter = zapcore.EpochNanosTimeEncoder
	case "iso8601":
		timeFormatter = zapcore.ISO8601TimeEncoder
	default:
		timeFormat := lec.TimeFormat
		switch lec.TimeFormat {
		case "rfc3339":
			timeFormat = time.RFC3339
		case "rfc3339_nano":
			timeFormat = time.RFC3339Nano
		case "wall":
			timeFormat = "2006/01/02 15:04:05"
		case "wall_milli":
			timeFormat = "2006/01/02 15:04:05.000"
		case "wall_nano":
			timeFormat = "2006/01/02 15:04:05.000000000"
		case "common_log":
			timeFormat = "02/Jan/2006:15:04:05 -0700"
		}
		timeFormatter = func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) {
			var time time.Time
			if lec.TimeLocal {
				time = ts.Local()
			} else {
				time = ts.UTC()
			}
			encoder.AppendString(time.Format(timeFormat))
		}
	}
	cfg.EncodeTime = timeFormatter

	// duration format
	var durFormatter zapcore.DurationEncoder
	switch lec.DurationFormat {
	case "s", "second", "seconds":
		durFormatter = zapcore.SecondsDurationEncoder
	case "ns", "nano", "nanos":
		durFormatter = zapcore.NanosDurationEncoder
	case "ms", "milli", "millis":
		durFormatter = zapcore.MillisDurationEncoder
	case "string":
		durFormatter = zapcore.StringDurationEncoder
	default:
		durFormatter = zapcore.SecondsDurationEncoder
	}
	cfg.EncodeDuration = durFormatter

	// level format
	var levelFormatter zapcore.LevelEncoder
	switch lec.LevelFormat {
	case "", "lower":
		levelFormatter = zapcore.LowercaseLevelEncoder
	case "upper":
		levelFormatter = zapcore.CapitalLevelEncoder
	case "color":
		levelFormatter = zapcore.CapitalColorLevelEncoder
	}
	cfg.EncodeLevel = levelFormatter

	return cfg
}

Cognitive complexity: 46, Cyclomatic complexity: 31

Uses: time.RFC3339, time.RFC3339Nano, time.Time, zap.NewProductionEncoderConfig, zapcore.CapitalColorLevelEncoder, zapcore.CapitalLevelEncoder, zapcore.DurationEncoder, zapcore.EpochMillisTimeEncoder, zapcore.EpochNanosTimeEncoder, zapcore.EpochTimeEncoder, zapcore.ISO8601TimeEncoder, zapcore.LevelEncoder, zapcore.LowercaseLevelEncoder, zapcore.MillisDurationEncoder, zapcore.NanosDurationEncoder, zapcore.PrimitiveArrayEncoder, zapcore.SecondsDurationEncoder, zapcore.StringDurationEncoder, zapcore.TimeEncoder.

func (*QueryFilter) Validate

Validate checks that action types are correct.

func (f *QueryFilter) Validate() error {
	for _, a := range f.Actions {
		if err := a.Type.IsValid(); err != nil {
			return err
		}
	}

	return nil
}

Cognitive complexity: 5, Cyclomatic complexity: 3

func (*fileMode) MarshalJSON

MarshalJSON satisfies json.Marshaler.

func (m *fileMode) MarshalJSON() ([]byte, error) {
	return []byte(fmt.Sprintf("\"%04o\"", *m)), nil
}

Cognitive complexity: 0, Cyclomatic complexity: 1

Uses: fmt.Sprintf.

func (*fileMode) UnmarshalJSON

UnmarshalJSON satisfies json.Unmarshaler.

func (m *fileMode) UnmarshalJSON(b []byte) error {
	if len(b) == 0 {
		return io.EOF
	}

	var s string
	if err := json.Unmarshal(b, &s); err != nil {
		return err
	}

	mode, err := parseFileMode(s)
	if err != nil {
		return err
	}

	*m = fileMode(mode)
	return err
}

Cognitive complexity: 6, Cyclomatic complexity: 4

Uses: io.EOF, json.Unmarshal.

func (*redialerConn) Write

Write wraps the underlying Conn.Write method, but if that fails, it will re-dial the connection anew and try writing again.

func (reconn *redialerConn) Write(b []byte) (n int, err error) {
	reconn.connMu.RLock()
	conn := reconn.Conn
	reconn.connMu.RUnlock()
	if conn != nil {
		if n, err = conn.Write(b); err == nil {
			return
		}
	}

	// problem with the connection - lock it and try to fix it
	reconn.connMu.Lock()
	defer reconn.connMu.Unlock()

	// if multiple concurrent writes failed on the same broken conn, then
	// one of them might have already re-dialed by now; try writing again
	if reconn.Conn != nil {
		if n, err = reconn.Conn.Write(b); err == nil {
			return
		}
	}

	// there's still a problem, so try to re-attempt dialing the socket
	// if some time has passed in which the issue could have potentially
	// been resolved - we don't want to block at every single log
	// emission (!) - see discussion in #4111
	if time.Since(reconn.lastRedial) > 10*time.Second {
		reconn.lastRedial = time.Now()
		conn2, err2 := reconn.dial()
		if err2 != nil {
			// logger socket still offline; instead of discarding the log, dump it to stderr
			os.Stderr.Write(b)
			return
		}
		if n, err = conn2.Write(b); err == nil {
			if reconn.Conn != nil {
				reconn.Conn.Close()
			}
			reconn.Conn = conn2
		}
	} else {
		// last redial attempt was too recent; just dump to stderr for now
		os.Stderr.Write(b)
	}

	return
}

Cognitive complexity: 18, Cyclomatic complexity: 9

Uses: os.Stderr, time.Now, time.Second, time.Since.

func (AppendEncoder) AddArray

AddArray is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddArray(key string, marshaler zapcore.ArrayMarshaler) error {
	return fe.wrapped.AddArray(key, marshaler)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddBinary

AddBinary is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddBinary(key string, value []byte) {
	fe.wrapped.AddBinary(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddBool

AddBool is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddBool(key string, value bool) {
	fe.wrapped.AddBool(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddByteString

AddByteString is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddByteString(key string, value []byte) {
	fe.wrapped.AddByteString(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddComplex128

AddComplex128 is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddComplex128(key string, value complex128) {
	fe.wrapped.AddComplex128(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddComplex64

AddComplex64 is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddComplex64(key string, value complex64) {
	fe.wrapped.AddComplex64(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddDuration

AddDuration is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddDuration(key string, value time.Duration) {
	fe.wrapped.AddDuration(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddFloat32

AddFloat32 is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddFloat32(key string, value float32) {
	fe.wrapped.AddFloat32(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddFloat64

AddFloat64 is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddFloat64(key string, value float64) {
	fe.wrapped.AddFloat64(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddInt

AddInt is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddInt(key string, value int) {
	fe.wrapped.AddInt(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddInt16

AddInt16 is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddInt16(key string, value int16) {
	fe.wrapped.AddInt16(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddInt32

AddInt32 is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddInt32(key string, value int32) {
	fe.wrapped.AddInt32(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddInt64

AddInt64 is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddInt64(key string, value int64) {
	fe.wrapped.AddInt64(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddInt8

AddInt8 is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddInt8(key string, value int8) {
	fe.wrapped.AddInt8(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddObject

AddObject is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddObject(key string, marshaler zapcore.ObjectMarshaler) error {
	return fe.wrapped.AddObject(key, marshaler)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddReflected

AddReflected is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddReflected(key string, value any) error {
	return fe.wrapped.AddReflected(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddString

AddString is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddString(key, value string) {
	fe.wrapped.AddString(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddTime

AddTime is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddTime(key string, value time.Time) {
	fe.wrapped.AddTime(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddUint

AddUint is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddUint(key string, value uint) {
	fe.wrapped.AddUint(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddUint16

AddUint16 is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddUint16(key string, value uint16) {
	fe.wrapped.AddUint16(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddUint32

AddUint32 is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddUint32(key string, value uint32) {
	fe.wrapped.AddUint32(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddUint64

AddUint64 is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddUint64(key string, value uint64) {
	fe.wrapped.AddUint64(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddUint8

AddUint8 is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddUint8(key string, value uint8) {
	fe.wrapped.AddUint8(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) AddUintptr

AddUintptr is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) AddUintptr(key string, value uintptr) {
	fe.wrapped.AddUintptr(key, value)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (AppendEncoder) CaddyModule

CaddyModule returns the Caddy module information.

func (AppendEncoder) CaddyModule() caddy.ModuleInfo {
	return caddy.ModuleInfo{
		ID:	"caddy.logging.encoders.append",
		New:	func() caddy.Module { return new(AppendEncoder) },
	}
}

Cognitive complexity: 2, Cyclomatic complexity: 1

func (AppendEncoder) Clone

Clone is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) Clone() zapcore.Encoder {
	return AppendEncoder{
		Fields:		fe.Fields,
		wrapped:	fe.wrapped.Clone(),
		repl:		fe.repl,
	}
}

Cognitive complexity: 1, Cyclomatic complexity: 1

func (AppendEncoder) EncodeEntry

EncodeEntry partially implements the zapcore.Encoder interface.

func (fe AppendEncoder) EncodeEntry(ent zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) {
	fe.wrapped = fe.wrapped.Clone()
	for _, field := range fields {
		field.AddTo(fe)
	}

	// append fields from config
	for key, value := range fe.Fields {
		// if the value is a string
		if str, ok := value.(string); ok {
			isPlaceholder := strings.HasPrefix(str, "{") &&
				strings.HasSuffix(str, "}") &&
				strings.Count(str, "{") == 1
			if isPlaceholder {
				// and it looks like a placeholder, evaluate it
				replaced, _ := fe.repl.Get(strings.Trim(str, "{}"))
				zap.Any(key, replaced).AddTo(fe)
			} else {
				// just use the string as-is
				zap.String(key, str).AddTo(fe)
			}
		} else {
			// not a string, so use the value as any
			zap.Any(key, value).AddTo(fe)
		}
	}

	return fe.wrapped.EncodeEntry(ent, nil)
}

Cognitive complexity: 14, Cyclomatic complexity: 7

Uses: strings.Count, strings.HasPrefix, strings.HasSuffix, strings.Trim, zap.Any, zap.String.

func (AppendEncoder) OpenNamespace

OpenNamespace is part of the zapcore.ObjectEncoder interface.

func (fe AppendEncoder) OpenNamespace(key string) {
	fe.wrapped.OpenNamespace(key)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (DeleteFilter) Filter

Filter filters the input field.

func (DeleteFilter) Filter(in zapcore.Field) zapcore.Field {
	in.Type = zapcore.SkipType
	return in
}

Cognitive complexity: 0, Cyclomatic complexity: 1

Uses: zapcore.SkipType.

func (FileWriter) OpenWriter

OpenWriter opens a new file writer.

func (fw FileWriter) OpenWriter() (io.WriteCloser, error) {
	if fw.Mode == 0 {
		fw.Mode = 0o600
	}

	// roll log files by default
	if fw.Roll == nil || *fw.Roll {
		if fw.RollSizeMB == 0 {
			fw.RollSizeMB = 100
		}
		if fw.RollCompress == nil {
			compress := true
			fw.RollCompress = &compress
		}
		if fw.RollKeep == 0 {
			fw.RollKeep = 10
		}
		if fw.RollKeepDays == 0 {
			fw.RollKeepDays = 90
		}

		// create the file if it does not exist with the right mode.
		// lumberjack will reuse the file mode across log rotation.
		f_tmp, err := os.OpenFile(fw.Filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.FileMode(fw.Mode))
		if err != nil {
			return nil, err
		}
		f_tmp.Close()
		// ensure already existing files have the right mode,
		// since OpenFile will not set the mode in such case.
		if err = os.Chmod(fw.Filename, os.FileMode(fw.Mode)); err != nil {
			return nil, err
		}

		return &lumberjack.Logger{
			Filename:	fw.Filename,
			MaxSize:	fw.RollSizeMB,
			MaxAge:		fw.RollKeepDays,
			MaxBackups:	fw.RollKeep,
			LocalTime:	fw.RollLocalTime,
			Compress:	*fw.RollCompress,
		}, nil
	}

	// otherwise just open a regular file
	return os.OpenFile(fw.Filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.FileMode(fw.Mode))
}

Cognitive complexity: 17, Cyclomatic complexity: 10

Uses: os.Chmod, os.FileMode, os.O_APPEND, os.O_CREATE, os.O_WRONLY, os.OpenFile.

func (FileWriter) String

func (fw FileWriter) String() string {
	fpath, err := caddy.FastAbs(fw.Filename)
	if err == nil {
		return fpath
	}
	return fw.Filename
}

Cognitive complexity: 2, Cyclomatic complexity: 2

func (FileWriter) WriterKey

WriterKey returns a unique key representing this fw.

func (fw FileWriter) WriterKey() string {
	return "file:" + fw.Filename
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (filterAction) IsValid

func (a filterAction) IsValid() error {
	switch a {
	case replaceAction, deleteAction, hashAction:
		return nil
	}

	return errors.New("invalid action type")
}

Cognitive complexity: 3, Cyclomatic complexity: 3

Uses: errors.New.

func (logObjectMarshalerWrapper) MarshalLogObject

MarshalLogObject implements the zapcore.ObjectMarshaler interface.

func (mom logObjectMarshalerWrapper) MarshalLogObject(_ zapcore.ObjectEncoder) error {
	return mom.marsh.MarshalLogObject(mom.enc)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

Private functions

func hash

hash returns the first 4 bytes of the SHA-256 hash of the given data as hexadecimal

hash (s string) string
References: fmt.Sprintf, sha256.Sum256.

func init

init ()

func parseFileMode

parseFileMode parses a file mode string, adding support for chmod unix command like 1 to 4 digital octal values.

parseFileMode (s string) (os.FileMode, error)
References: fmt.Sprintf, os.FileMode, strconv.ParseUint.

func dial

dial () (net.Conn, error)
References: net.DialTimeout.

func filtered

filtered returns true if the field was filtered. If true is returned, the field was filtered and added to the underlying encoder (so do not do that again). If false was returned, the field has not yet been added to the underlying encoder.

filtered (key string, value any) bool
References: zap.Any.

func mask

mask (s string) string
References: net.JoinHostPort, net.ParseIP, net.SplitHostPort, strings.Split, strings.TrimSpace, strings.TrimSuffix.

func processQueryString

processQueryString (s string) string
References: url.Parse.


Tests

Files: 2. Third party imports: 1. Imports from organisation: 0. Tests: 18. Benchmarks: 0.

Test functions

TestCookieFilter

References: caddyhttp.LoggableStringArray, zapcore.Field.

TestFileCreationMode

References: os.FileMode, os.MkdirTemp, os.RemoveAll, os.Stat, path.Join, syscall.Umask, testing.T.

TestFileModeConfig

References: caddyfile.Dispenser, caddyfile.NewTestDispenser, testing.T.

TestFileModeJSON

References: json.Unmarshal, testing.T.

TestFileModeModification

References: os.FileMode, os.MkdirTemp, os.O_APPEND, os.O_CREATE, os.O_WRONLY, os.OpenFile, os.RemoveAll, os.Stat, path.Join, syscall.Umask.

TestFileModeToJSON

References: json.Marshal, testing.T.

TestFileRotationPreserveMode

References: os.FileMode, os.MkdirTemp, os.ReadDir, os.RemoveAll, os.Stat, path.Join, path.Match, syscall.Umask.

TestHashFilterMultiValue

References: caddyhttp.LoggableStringArray, zapcore.Field.

TestHashFilterSingleValue

References: zapcore.Field.

TestIPMaskCommaValue

References: zapcore.Field.

TestIPMaskMultiValue

References: caddyhttp.LoggableStringArray, zapcore.Field.

TestIPMaskSingleValue

References: zapcore.Field.

TestQueryFilterMultiValue

References: caddyhttp.LoggableStringArray, zapcore.Field.

TestQueryFilterSingleValue

References: zapcore.Field.

TestRegexpFilterMultiValue

References: caddyhttp.LoggableStringArray, zapcore.Field.

TestRegexpFilterSingleValue

References: zapcore.Field.

TestValidateCookieFilter

TestValidateQueryFilter