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!
That said, the examples below are just a demonstration. I am not claiming at all that they are efficient replacements of standard functionality. :)
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.
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
NOTE: I am creating a single string from multiple substrings and appending it to the array. For some reason, if I appended the substrings separately, zap is padding them with spaces.
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.