The various implementations of field encoders provided in zap
can sometimes feel inadequate. For
example, you might want the logging output to be similar to that in syslog or other common log
formats. You might want the timestamps in the log to ignore seconds, or the log level to be wrapped
within square brackets.
To have your own custom formatters for the metadata fields you need to write custom encoders.
Contents:
This post is third in a series of posts showing different ways of using zap
. The other
posts are Simple use cases, Creating custom
loggers and Working With Global Loggers
This documentation was written for zap v1.8.
The full source for the code extracts in the rest of the post is here
Performance considerations
You can use custom encoders for formatting time, level, caller, etc. One caveat is that you need these encoders to be as efficient as possible so as to not negate the memory/speed advantages of zap itself. After all, these functions are called for every line of log to be emitted! So avoid creating temporary variables, or doing any expensive calculations.
That said, the examples below are just a demonstration. I am not claiming at all that they are efficient replacements of the default functionality. 😄
Customizing timestamp formatting
Here is an implementation which uses the syslog format often found in the wild.
func SyslogTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(t.Format("Jan 2 15:04:05"))
}
...
cfg.EncoderConfig.EncodeTime = SyslogTimeEncoder
logger, _ = cfg.Build()
logger.Info("This should have a syslog style timestamp")
Output:
May 2 18:54:55 INFO This should have a syslog style timestamp
If you noticed in the implementation that the encoder is supposed to append primitives to an array like object. zap uses this array to efficiently encode output with minimal memory allocations.
Customizing level formatting
func CustomLevelEncoder(level zapcore.Level, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString("[" + level.CapitalString() + "]")
}
...
cfg.EncoderConfig.EncodeLevel = CustomLevelEncoder
logger, _ = cfg.Build()
logger.Info("This should have a bracketed level name")
Output:
May 2 18:54:55 [INFO] This should have a bracketed level name
I am creating a single string from multiple substrings and appending it to the array.
This might cause temporary memory allocations. I had to do this because if I appended the substrings
separately, it seemed to me that zap
was considering them as separate fields in the output and
spacing them out with whitespace.
Similar customization can be done for other metadata fields as well. You can look at the zap source to find the general pattern of these implementations.
comments powered by Disqus