github.com/caddyserver/caddy/v2/modules/logging
No package summary is available.
- Package
- Constants
- Vars
- Types
- AppendEncoder
- ConsoleEncoder
- CookieFilter
- DeleteFilter
- FileWriter
- FilterEncoder
- HashFilter
- IPMaskFilter
- JSONEncoder
- LogEncoderConfig
- LogFieldFilter
- MockCore
- NetWriter
- QueryFilter
- RegexpFilter
- RenameFilter
- ReplaceFilter
- cookieFilterAction
- fileMode
- filterAction
- logObjectMarshalerWrapper
- nopEncoder
- queryFilterAction
- redialerConn
- Functions
- func (*AppendEncoder) ConfigureDefaultFormat
- func (*AppendEncoder) Provision
- func (*AppendEncoder) UnmarshalCaddyfile
- func (*LogEncoderConfig) ZapcoreEncoderConfig
- func (*QueryFilter) Validate
- func (*fileMode) MarshalJSON
- func (*fileMode) UnmarshalJSON
- func (*redialerConn) Write
- func (AppendEncoder) AddArray
- func (AppendEncoder) AddBinary
- func (AppendEncoder) AddBool
- func (AppendEncoder) AddByteString
- func (AppendEncoder) AddComplex128
- func (AppendEncoder) AddComplex64
- func (AppendEncoder) AddDuration
- func (AppendEncoder) AddFloat32
- func (AppendEncoder) AddFloat64
- func (AppendEncoder) AddInt
- func (AppendEncoder) AddInt16
- func (AppendEncoder) AddInt32
- func (AppendEncoder) AddInt64
- func (AppendEncoder) AddInt8
- func (AppendEncoder) AddObject
- func (AppendEncoder) AddReflected
- func (AppendEncoder) AddString
- func (AppendEncoder) AddTime
- func (AppendEncoder) AddUint
- func (AppendEncoder) AddUint16
- func (AppendEncoder) AddUint32
- func (AppendEncoder) AddUint64
- func (AppendEncoder) AddUint8
- func (AppendEncoder) AddUintptr
- func (AppendEncoder) CaddyModule
- func (AppendEncoder) Clone
- func (AppendEncoder) EncodeEntry
- func (AppendEncoder) OpenNamespace
- func (DeleteFilter) Filter
- func (FileWriter) OpenWriter
- func (FileWriter) String
- func (FileWriter) WriterKey
- func (filterAction) IsValid
- func (logObjectMarshalerWrapper) MarshalLogObject
- Private functions
- Tests
- Test functions
- TestCookieFilter
- TestFileCreationMode
- TestFileModeConfig
- TestFileModeJSON
- TestFileModeModification
- TestFileModeToJSON
- TestFileRotationPreserveMode
- TestHashFilterMultiValue
- TestHashFilterSingleValue
- TestIPMaskCommaValue
- TestIPMaskMultiValue
- TestIPMaskSingleValue
- TestQueryFilterMultiValue
- TestQueryFilterSingleValue
- TestRegexpFilterMultiValue
- TestRegexpFilterSingleValue
- TestValidateCookieFilter
- TestValidateQueryFilter
- Test functions
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
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
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
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
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
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
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
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
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
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
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
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.