Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow configurable stacktrace encoding #1371

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
50 changes: 26 additions & 24 deletions config.go
Expand Up @@ -123,18 +123,19 @@ type Config struct {
// cfg.EncodeTime = zapcore.ISO8601TimeEncoder
func NewProductionEncoderConfig() zapcore.EncoderConfig {
return zapcore.EncoderConfig{
TimeKey: "ts",
LevelKey: "level",
NameKey: "logger",
CallerKey: "caller",
FunctionKey: zapcore.OmitKey,
MessageKey: "msg",
StacktraceKey: "stacktrace",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.LowercaseLevelEncoder,
EncodeTime: zapcore.EpochTimeEncoder,
EncodeDuration: zapcore.SecondsDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
TimeKey: "ts",
LevelKey: "level",
NameKey: "logger",
CallerKey: "caller",
FunctionKey: zapcore.OmitKey,
MessageKey: "msg",
StacktraceKey: "stacktrace",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.LowercaseLevelEncoder,
EncodeTime: zapcore.EpochTimeEncoder,
EncodeDuration: zapcore.SecondsDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
EncodeStacktrace: zapcore.FullStacktraceEncoder,
}
}

Expand Down Expand Up @@ -200,18 +201,19 @@ func NewProductionConfig() Config {
func NewDevelopmentEncoderConfig() zapcore.EncoderConfig {
return zapcore.EncoderConfig{
// Keys can be anything except the empty string.
TimeKey: "T",
LevelKey: "L",
NameKey: "N",
CallerKey: "C",
FunctionKey: zapcore.OmitKey,
MessageKey: "M",
StacktraceKey: "S",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.CapitalLevelEncoder,
EncodeTime: zapcore.ISO8601TimeEncoder,
EncodeDuration: zapcore.StringDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
TimeKey: "T",
LevelKey: "L",
NameKey: "N",
CallerKey: "C",
FunctionKey: zapcore.OmitKey,
MessageKey: "M",
StacktraceKey: "S",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.CapitalLevelEncoder,
EncodeTime: zapcore.ISO8601TimeEncoder,
EncodeDuration: zapcore.StringDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
EncodeStacktrace: zapcore.FullStacktraceEncoder,
}
}

Expand Down
18 changes: 16 additions & 2 deletions zapcore/console_encoder.go
Expand Up @@ -101,6 +101,7 @@
arr.AppendString(ent.Caller.Function)
}
}

for i := range arr.elems {
if i > 0 {
line.AppendString(c.ConsoleSeparator)
Expand All @@ -119,10 +120,23 @@
c.writeContext(line, fields)

// If there's no stacktrace key, honor that; this allows users to force
// single-line output.
// single-line output by avoiding printing the stacktrace.
if ent.Stack != "" && c.StacktraceKey != "" {
line.AppendByte('\n')
line.AppendString(ent.Stack)

if c.EncodeStacktrace != nil {
arr = getSliceEncoder()
c.EncodeStacktrace(ent.Stack, arr)
for i := range arr.elems {
if i > 0 {
line.AppendString(c.ConsoleSeparator)
}

Check warning on line 133 in zapcore/console_encoder.go

View check run for this annotation

Codecov / codecov/patch

zapcore/console_encoder.go#L132-L133

Added lines #L132 - L133 were not covered by tests
fmt.Fprint(line, arr.elems[i])
}
putSliceEncoder(arr)
} else {
line.AppendString(ent.Stack)
}

Check warning on line 139 in zapcore/console_encoder.go

View check run for this annotation

Codecov / codecov/patch

zapcore/console_encoder.go#L137-L139

Added lines #L137 - L139 were not covered by tests
}

line.AppendString(c.LineEnding)
Expand Down
21 changes: 17 additions & 4 deletions zapcore/encoder.go
Expand Up @@ -270,6 +270,18 @@ func (e *DurationEncoder) UnmarshalText(text []byte) error {
return nil
}

// A StacktraceEncoder serializes a stacktrace
//
// This function must make exactly one call
// to a PrimitiveArrayEncoder's Append* method.
type StacktraceEncoder func(string, PrimitiveArrayEncoder)

// FullStacktraceEncoder passes down the full stacktrace as a string to the enc
arwineap marked this conversation as resolved.
Show resolved Hide resolved
func FullStacktraceEncoder(stacktrace string, enc PrimitiveArrayEncoder) {
// TODO: consider using a byte-oriented API to save an allocation.
arwineap marked this conversation as resolved.
Show resolved Hide resolved
enc.AppendString(stacktrace)
}

// A CallerEncoder serializes an EntryCaller to a primitive type.
//
// This function must make exactly one call
Expand Down Expand Up @@ -343,10 +355,11 @@ type EncoderConfig struct {
// Configure the primitive representations of common complex types. For
// example, some users may want all time.Times serialized as floating-point
// seconds since epoch, while others may prefer ISO8601 strings.
EncodeLevel LevelEncoder `json:"levelEncoder" yaml:"levelEncoder"`
EncodeTime TimeEncoder `json:"timeEncoder" yaml:"timeEncoder"`
EncodeDuration DurationEncoder `json:"durationEncoder" yaml:"durationEncoder"`
EncodeCaller CallerEncoder `json:"callerEncoder" yaml:"callerEncoder"`
EncodeLevel LevelEncoder `json:"levelEncoder" yaml:"levelEncoder"`
EncodeTime TimeEncoder `json:"timeEncoder" yaml:"timeEncoder"`
EncodeDuration DurationEncoder `json:"durationEncoder" yaml:"durationEncoder"`
EncodeCaller CallerEncoder `json:"callerEncoder" yaml:"callerEncoder"`
EncodeStacktrace StacktraceEncoder `json:"stacktraceEncoder" yaml:"stacktraceEncoder"`
arwineap marked this conversation as resolved.
Show resolved Hide resolved
// Unlike the other primitive type encoders, EncodeName is optional. The
// zero value falls back to FullNameEncoder.
EncodeName NameEncoder `json:"nameEncoder" yaml:"nameEncoder"`
Expand Down