Explain
- A previous translation of a tutorial (without backing up the original address, the ladder was sealed). Add the original address after finding it
text
Using the default recorder saves time, but if you decide to adjust the recorder, you need to explore ways to customize the recorder
Using zap configuration structure to create recorders
You can use configuration zap.Config to create a recorder, which is a structure that can be filled with the required values, and then call the. Build() method of the structure to get the recorder.
cfg := zap.Config{...} logger, err := cfg.Build()
Note that the structure of zap.Config does not have default values, providing values for at least three settings required by zap
- Encoder: Just add an Encoding:"XXX" and use JSON to create a JSON encoder with another value of console
- You can use the structure zapcore.EncoderConfig to customize the encoder (almost certainly, because the default is not very useful)
- level enabler: This is an interface type that allows zap to determine whether a particular level of message should be displayed. In the zap configuration structure, you can use the Atomic Level wrapper in the Level field to provide this type.
- sink: The output target of the log, which can specify multiple output paths using the Output Paths field, is sent to all these files. Like stderr and stdout are also possible
Customized encoder
It is not enough to set the type of encoder in the configuration structure. By default, json only outputs the fields specifically provided in the log message.
Here's the minimum configuration that won't throw errors when calling the. Build() method
logger, _ := zap.Config{ Encoding: "json", Level: zap.NewAtomicLevelAt(zap.DebugLevel), OutputPaths: []string{"stdout"}, }.Build() logger.Info("This is an INFO message with fileds", zap.String("region", "us-west"), zap.Int("id", 2))
output
{"region":"us-west","id":2}
As you can see, the log information is not printed out!
To add information to json encoder, you need to specify the json key that will have this value in the output
logger, _ := zap.Config{ Encoding: "json", Level: zap.NewAtomicLevelAt(zap.DebugLevel), OutputPaths: []string{"stdout"}, EncoderConfig: zapcore.EncoderConfig{ MessageKey: "message", // <--- }, }.Build() logger.Info("This is an INFO message with fileds", zap.String("region", "us-west"), zap.Int("id", 2))
output
{"message":"This is an INFO message with fileds","region":"us-west","id":2}
zap can add more metadata like message, such as level name, timestamp, caller, stacktrace and so on. Unless the JSON key corresponding to the metadata is explicitly indicated, no will be displayed.
Note: These metadata names must match the encoder, or zap will make a mistake
Example:
cfg := zap.Config{ Encoding: "json", Level: zap.NewAtomicLevelAt(zap.DebugLevel), OutputPaths: []string{"stdout"}, ErrorOutputPaths: []string{"stderr"}, EncoderConfig: zapcore.EncoderConfig{ MessageKey: "message", // <--- LevelKey: "level", EncodeLevel: zapcore.CapitalLevelEncoder, TimeKey: "time", EncodeTime: zapcore.ISO8601TimeEncoder, CallerKey: "caller", EncodeCaller: zapcore.ShortCallerEncoder, }, } logger, _ := cfg.Build() logger.Info("This is an INFO message with fileds", zap.String("region", "us-west"), zap.Int("id", 2))
output
{"level":"INFO","time":"2018-10-31T14:59:45.238+0800","caller":"zap_config/main.go:29","message":"This is an INFO message with fileds","region":"us-west","id":2}
Other options for encoder metadata fields
Each encoder can be customized as needed. Here are the different implementations provided by zap
- timestamp can be ISO8601 Format output, which can be seconds,milliseconds Even to the extent that nanoseconds Format output
- level: It can be capital or lowercase, and they even have colored Options. It is important to note that color options are not meaningful in JSON encoders
- caller: Can be in relative format short And absolute format full display
Dynamic Change of Recorder Behavior
You can clone recorders from existing recorders and make some modifications to their behavior
- logger.AddCaller() Add caller
- logger.AddStacktrace() adds stack traces to messages at a given level and above
- logger.Fields() adds the specified field to all messages output by the new logger. This approach reduces memory allocation and speeds up logging compared to specifying fields during actual log calls
- logger.WrapCore() allows you to modify or even completely replace the encoder, level, and sink contained in the recorder. Here's an example
fmt.Printf("\n*** Using a JSON encoder, at debug level, sending output tu stuout, all possible keys specified\n\n") cfg := zap.Config{ Encoding: "json", Level: zap.NewAtomicLevelAt(zapcore.DebugLevel), OutputPaths: []string{"stderr"}, ErrorOutputPaths: []string{"stderr"}, EncoderConfig: zapcore.EncoderConfig{ MessageKey: "message", LevelKey: "level", EncodeLevel: zapcore.CapitalLevelEncoder, TimeKey: "time", EncodeTime: zapcore.ISO8601TimeEncoder, CallerKey: "caller", EncodeCaller: zapcore.ShortCallerEncoder, }, } logger, _ := cfg.Build() logger.Info("This is an INFO message") fmt.Printf("\n*** Same logger with console loggin enable instead\n\n") logger.WithOptions( zap.WrapCore( func(zapcore.Core) zapcore.Core { return zapcore.NewCore(zapcore.NewConsoleEncoder(cfg.EncoderConfig), zapcore.AddSync(os.Stderr), zapcore.DebugLevel) })).Info("This is an INFO message")
output
*** Using a JSON encoder, at debug level, sending output tu stuout, all possible keys specified {"level":"INFO","time":"2018-11-01T08:59:12.984+0800","caller":"wrap_core/main.go:35","message":"This is an INFO message"} *** Same logger with console loggin enable instead 2018-11-01T08:59:12.984+0800 INFO wrap_core/main.go:43 This is an INFO message