Blazing fast, structured, leveled logging in Go.
npx @tessl/cli install tessl/golang-zap@1.27.0Zap is a blazingly fast, structured logging library for Go, providing both high-performance strongly-typed logging (Logger) and ergonomic loosely-typed logging (SugaredLogger). It offers zero-allocation JSON encoding, flexible log levels, and extensive customization through its modular architecture.
go get -u go.uber.org/zapimport (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)For testing utilities:
import (
"go.uber.org/zap/zaptest"
"go.uber.org/zap/zaptest/observer"
)For integrations:
import (
"go.uber.org/zap/zapgrpc" // gRPC integration
"go.uber.org/zap/zapio" // io.Writer integration
)import "go.uber.org/zap"
// Create a production logger with sensible defaults
logger, _ := zap.NewProduction()
defer logger.Sync()
// Structured logging with strongly-typed fields
logger.Info("user logged in",
zap.String("username", "alice"),
zap.Int("user_id", 42),
zap.Duration("latency", 125*time.Millisecond),
)
// For more ergonomic API, use SugaredLogger
sugar := logger.Sugar()
sugar.Infow("user logged in",
"username", "alice",
"user_id", 42,
)Zap's architecture separates concerns for maximum flexibility and performance:
Logger: Strongly-typed API that avoids reflection and allocations. Every field must be explicitly typed using field constructors like zap.String(), zap.Int(), etc. Optimal for hot paths where every microsecond matters.
SugaredLogger: Loosely-typed API that accepts interface{} values and uses reflection. More ergonomic with Printf-style and structured logging methods. 4-10x slower than Logger but still faster than most alternatives.
Zap is built on the zapcore package, which defines low-level interfaces:
NewProduction(), NewDevelopment() for common scenariosNew() with custom Core for maximum controlProvides Logger and SugaredLogger types with methods for all log levels, dynamic level changes, and configuration options.
// Logger provides strongly-typed, high-performance logging
type Logger struct { /* ... */ }
func NewProduction(options ...Option) (*Logger, error)
func NewDevelopment(options ...Option) (*Logger, error)
func (log *Logger) Info(msg string, fields ...Field)
func (log *Logger) Error(msg string, fields ...Field)
func (log *Logger) With(fields ...Field) *Logger
func (log *Logger) Sugar() *SugaredLogger// SugaredLogger provides ergonomic, loosely-typed logging
type SugaredLogger struct { /* ... */ }
func (s *SugaredLogger) Infow(msg string, keysAndValues ...interface{})
func (s *SugaredLogger) Infof(template string, args ...interface{})
func (s *SugaredLogger) Info(args ...interface{})// AtomicLevel enables runtime level changes
type AtomicLevel struct { /* ... */ }
func NewAtomicLevel() AtomicLevel
func (lvl AtomicLevel) SetLevel(l zapcore.Level)
func (lvl AtomicLevel) ServeHTTP(w http.ResponseWriter, r *http.Request)Over 100 field constructor functions for efficient, strongly-typed structured logging. Fields avoid allocations and reflection for maximum performance.
// Primitive types
func String(key string, val string) Field
func Int(key string, val int) Field
func Bool(key string, val bool) Field
func Float64(key string, val float64) Field
// Time types
func Time(key string, val time.Time) Field
func Duration(key string, val time.Duration) Field
// Error types
func Error(err error) Field
func NamedError(key string, err error) Field
// Advanced types
func Any(key string, value interface{}) Field
func Object(key string, val zapcore.ObjectMarshaler) Field
func Array(key string, val zapcore.ArrayMarshaler) Field
func Stringer(key string, val fmt.Stringer) Field
func Stringers[T fmt.Stringer](key string, values []T) Field
func Skip() FieldThe zapcore package provides low-level interfaces and implementations for extending zap's capabilities with custom encoders, cores, and write destinations.
// Core is the minimal interface for logging
type Core interface {
LevelEnabler
With([]Field) Core
Check(Entry, *CheckedEntry) *CheckedEntry
Write(Entry, []Field) error
Sync() error
}
// Encoder transforms entries to bytes
type Encoder interface {
ObjectEncoder
Clone() Encoder
EncodeEntry(Entry, []Field) (*buffer.Buffer, error)
}
// WriteSyncer is a thread-safe write destination
type WriteSyncer interface {
io.Writer
Sync() error
}Integration packages for gRPC logging and standard library io.Writer compatibility.
// zapgrpc provides gRPC-compatible logger
type Logger struct { /* ... */ }
func NewLogger(l *zap.Logger, options ...Option) *Logger
func (l *Logger) Info(args ...interface{})
func (l *Logger) Warning(args ...interface{})
func (l *Logger) Error(args ...interface{})// zapio provides io.Writer that logs to zap
type Writer struct {
Log *zap.Logger
Level zapcore.Level
}
func (w *Writer) Write(bs []byte) (n int, err error)Tools for testing log output including test loggers, in-memory observation, and assertion utilities.
// zaptest provides test logger
func NewLogger(t TestingT, opts ...LoggerOption) *zap.Logger
// observer captures logs in memory for assertions
type ObservedLogs struct { /* ... */ }
func New(enab zapcore.LevelEnabler) (zapcore.Core, *ObservedLogs)
func (o *ObservedLogs) All() []LoggedEntry
func (o *ObservedLogs) FilterMessage(msg string) *ObservedLogsZap provides global logger functions for convenience:
// Access global loggers
func L() *Logger
func S() *SugaredLogger
// Replace global loggers (returns restore function)
func ReplaceGlobals(logger *Logger) func()
// Redirect standard library log package
func RedirectStdLog(l *Logger) func()
func RedirectStdLogAt(l *Logger, level zapcore.Level) (func(), error)// Config provides declarative logger configuration
type Config struct {
Level AtomicLevel `json:"level" yaml:"level"`
Development bool `json:"development" yaml:"development"`
DisableCaller bool `json:"disableCaller" yaml:"disableCaller"`
DisableStacktrace bool `json:"disableStacktrace" yaml:"disableStacktrace"`
Sampling *SamplingConfig `json:"sampling" yaml:"sampling"`
Encoding string `json:"encoding" yaml:"encoding"`
EncoderConfig zapcore.EncoderConfig `json:"encoderConfig" yaml:"encoderConfig"`
OutputPaths []string `json:"outputPaths" yaml:"outputPaths"`
ErrorOutputPaths []string `json:"errorOutputPaths" yaml:"errorOutputPaths"`
InitialFields map[string]interface{} `json:"initialFields" yaml:"initialFields"`
}
func NewProductionConfig() Config
func NewDevelopmentConfig() Config
func (cfg Config) Build(opts ...Option) (*Logger, error)// SamplingConfig controls log sampling for rate limiting
type SamplingConfig struct {
Initial int `json:"initial" yaml:"initial"`
Thereafter int `json:"thereafter" yaml:"thereafter"`
Hook func(zapcore.Entry, zapcore.SamplingDecision) `json:"-" yaml:"-"`
}const (
DebugLevel = zapcore.DebugLevel // -1: Voluminous debug information
InfoLevel = zapcore.InfoLevel // 0: General informational messages
WarnLevel = zapcore.WarnLevel // 1: Warning messages
ErrorLevel = zapcore.ErrorLevel // 2: Error messages
DPanicLevel = zapcore.DPanicLevel // 3: Panic in development mode
PanicLevel = zapcore.PanicLevel // 4: Logs then panics
FatalLevel = zapcore.FatalLevel // 5: Logs then calls os.Exit(1)
)