Zap Concepts

From NovaOrdis Knowledge Base
Jump to navigation Jump to search

External

Internal

TODO

Overview

Zap is a logging framework for Go. It provides fast, structured, contextual and leveled logging.

The programming model involves creating a Logger object and invoking its API, for example logger.Info(...). Creation of Logger instances can be done in a number of way that are explored in the Logger Instance Creation section. There are actually two logging APIs, zap.Logger and zap.SugaredLogger. The former is appropriate for high-performance scenarios, but only supports a structured logging method signatures, while the latter has a more friendlier, and just slightly less performant syntax which is similar to that of fmt.Sprintf(). The difference is discussed in Two Logging APIs section.

Each logging invocation creates a log event with key/value pairs, as explained in Structured Logging. The rendering of the log events can be changed through configuration. These aspects are discussed in the Log Rendering section.

There is no global logger that can be used right away, though one can be configured. Use of global loggers should be avoided, though.

Zap supports the standard DEBUG, INFO, WARN and ERROR logging levels. It comes with a few new ones: PANIC, DPANIC and FATAL. The ERROR level requires special attention. There is no TRACE. More details are available in the Logging Levels section.

By default, loggers are unbuffered. This aspect is discussed in the Buffering section.

Implementation aspects are discussed in Implementation Details.

Logger Instance Creation

The framework comes with three preset constructors: zap.NewExample(), zap.NewProduction() and zap.NewDevelopment(). Each of these constructors internally create a logging core and set its encoder, output and level. These components are configured according to the type of logger. In case of the example logger, the encoder produces JSON structures that contain only two keys "level" and "msg", the default log level is DEBUG and the logs are send to stdout. In case of a production logger, the encoder produces JSON structures that contain "level", "ts", "msg" and "caller", the default log level is INFO, the "normal" logging is sent to stdout and error logging is sent to stderr and sampling is enabled. In case of a development logger, the encoder produces "console" encoding, which are human readable messages, the default log level is DEBUG, the "normal" logging is sent to stdout and error logging is sent to stderr and sampling is disabled.

logger := zap.NewExample()
logger, err := zap.NewProduction()
logger, err := zap.NewDevelopment()

These instances are OK if their configuration matches the use case. However, custom-configured instances can be created via two other methods.

  • Understand how I can get a logger instance “out of the blue” and how I can build a set of predefined loggers. Must figure out logging situation in tests. I must be able to start a test in debug mode and see the log.
  • Can I use a single instance? Is it thread safe?

Two Logging APIs

Structured Logging

Each logging invocation creates a log event. Zap calls these events log entries. The log entries are implemented as zapcore.Entry struct instances, so each carry by default the structure's fields: logging level, timestamp, logger name, message, caller and stack. The caller is a string containing the source code location where the log invocation was done, in form of <package>/<file-name>.go:<line>.

which carries an arbitrary number of key/value pair fields. Each entry represents a complete log message.


What about the log message?

Also see

Structured Logging

Log Rendering

The external representation of a log entry is produced by an encoder. The default encoder generates JSON structures, where the log entry's fields are represented as JSON map elements.

Logging Levels

Internally, the logging level are implemented as constants (zap.DebugLevel, zap.InfoLevel, zap.WarnLevel, zap.ErrorLevel, zap.DPanicLevel, zap.PanicLevel, zap.FatalLevel).

Custom Logging Levels

Configuration

Buffering

Sampling

Other Subjects

Child loggers.

Implementation Details

Each zap.Logger wraps around a core, which is configured with an encoder, an output and a logging level:

Zap.png

An encoder is the component that renders the external representation of the log entry instances. The default encoder is a JSON encoder, which renders entries as JSON structures. The encoder instance can be configured with a zapcore.EncoderConfig structure.

zap and zap core.

Best Practices

Sharing or not sharing logger instances?

Is it thread-safe?