What it is
Zap is Uber's structured logging library for Go, designed for very low allocation overhead in hot paths while producing machine-readable JSON.
Zap offers two APIs: the fast, strongly-typed Logger and the more ergonomic SugaredLogger. Both produce structured output with levels, sampling and configurable encoders.
Installation
go get -u go.uber.org/zapGetting started
The smallest useful thing you can do with it, and what each part means.
go
logger, _ := zap.NewProduction()
defer logger.Sync() // flush buffered entries before exit
logger.Info("request completed",
zap.String("method", "GET"),
zap.String("path", "/books"),
zap.Int("status", 200),
zap.Duration("took", elapsed),
)go
requestLogger := logger.With(
zap.String("request_id", id),
zap.String("user_id", userID),
)
requestLogger.Info("validating")
requestLogger.Warn("rate limit near", zap.Int("remaining", 3))
// every line carries request_id and user_id automaticallyAdvanced usage
Where the library earns its place over a simpler alternative.
go
config := zap.NewProductionConfig()
config.EncoderConfig.TimeKey = "ts"
config.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
config.Level = zap.NewAtomicLevelAt(zap.InfoLevel)
// Cap repetitive entries: first 100 per second, then 1 in 100.
config.Sampling = &zap.SamplingConfig{Initial: 100, Thereafter: 100}
logger, err := config.Build()
// The level is atomic, so it can be changed at runtime.
config.Level.SetLevel(zap.DebugLevel)Errors and fixes
The failures you are most likely to hit, and what actually resolves them.
- Logs are missing after the program exits
- Zap buffers. Call logger.Sync() before exit; note that Sync on stdout can return an error on some platforms, which is safe to ignore.
- Debug lines never appear
- NewProduction defaults to Info. Use NewDevelopment, or set the level explicitly via an AtomicLevel.
Best practices
- Call defer logger.Sync() in main so buffered entries are flushed on exit.
- Use the typed Logger in hot paths and SugaredLogger where convenience matters more.
- Attach request-scoped fields with With rather than repeating them at every call site.
- Never log secrets, tokens or full request bodies — structured logs are widely readable.
Background
Why it exists, and what it was reacting to.
Uber built Zap after finding that reflection-based logging dominated CPU profiles in high-throughput services. Its typed field API avoids reflection and allocation almost entirely.
