Zap provides two logger types: the strongly-typed Logger for maximum performance, and the more flexible SugaredLogger for convenience. Both types support leveled logging with structured context.
The Logger type provides strongly-typed, zero-allocation logging for performance-critical code paths. All context fields must be explicitly typed using field constructors.
type Logger struct {
// unexported fields
}func (log *Logger) Debug(msg string, fields ...Field)
func (log *Logger) Info(msg string, fields ...Field)
func (log *Logger) Warn(msg string, fields ...Field)
func (log *Logger) Error(msg string, fields ...Field)
func (log *Logger) DPanic(msg string, fields ...Field)
func (log *Logger) Panic(msg string, fields ...Field)
func (log *Logger) Fatal(msg string, fields ...Field)os.Exit(1)func (log *Logger) Log(lvl zapcore.Level, msg string, fields ...Field)Log at a specific level dynamically.
func (log *Logger) With(fields ...Field) *Logger
func (log *Logger) WithLazy(fields ...Field) *Logger
func (log *Logger) Named(s string) *Logger
func (log *Logger) WithOptions(opts ...Option) *Loggerfunc (log *Logger) Sugar() *SugaredLogger
func (log *Logger) Sync() errorfunc (log *Logger) Core() zapcore.Core
func (log *Logger) Name() string
func (log *Logger) Level() zapcore.Levelfunc (log *Logger) Check(lvl zapcore.Level, msg string) *zapcore.CheckedEntryCheck if a level is enabled and prepare an entry for writing. Useful for avoiding expensive field computation when logging is disabled.
logger, _ := zap.NewProduction()
defer logger.Sync()
logger.Info("user logged in",
zap.String("username", "alice"),
zap.String("ip", "192.168.1.100"),
zap.Duration("session_duration", 2*time.Hour),
)
logger.Error("database connection failed",
zap.String("host", "db.example.com"),
zap.Int("port", 5432),
zap.Error(err),
)// Add persistent context fields
requestLogger := logger.With(
zap.String("request_id", requestID),
zap.String("user_id", userID),
)
// All logs from requestLogger include request_id and user_id
requestLogger.Info("processing request")
requestLogger.Warn("slow query detected")authLogger := logger.Named("auth")
dbLogger := logger.Named("database")
authLogger.Info("authentication successful") // logged as "auth"
dbLogger.Error("query timeout") // logged as "database"if ce := logger.Check(zap.DebugLevel, "expensive debug info"); ce != nil {
// Only compute expensive fields if debug is enabled
ce.Write(
zap.String("data", computeExpensiveData()),
zap.Object("stats", gatherStatistics()),
)
}The SugaredLogger provides a more ergonomic API with Printf-style and loosely-typed structured logging. It's 4-10x faster than other structured logging packages but slightly slower than the strongly-typed Logger.
type SugaredLogger struct {
// unexported fields
}func (s *SugaredLogger) Debugw(msg string, keysAndValues ...interface{})
func (s *SugaredLogger) Infow(msg string, keysAndValues ...interface{})
func (s *SugaredLogger) Warnw(msg string, keysAndValues ...interface{})
func (s *SugaredLogger) Errorw(msg string, keysAndValues ...interface{})
func (s *SugaredLogger) DPanicw(msg string, keysAndValues ...interface{})
func (s *SugaredLogger) Panicw(msg string, keysAndValues ...interface{})
func (s *SugaredLogger) Fatalw(msg string, keysAndValues ...interface{})The "w" methods accept alternating key-value pairs for structured logging:
sugar.Infow("failed to fetch URL",
"url", "http://example.com",
"attempt", 3,
"backoff", time.Second,
)func (s *SugaredLogger) Debugf(template string, args ...interface{})
func (s *SugaredLogger) Infof(template string, args ...interface{})
func (s *SugaredLogger) Warnf(template string, args ...interface{})
func (s *SugaredLogger) Errorf(template string, args ...interface{})
func (s *SugaredLogger) DPanicf(template string, args ...interface{})
func (s *SugaredLogger) Panicf(template string, args ...interface{})
func (s *SugaredLogger) Fatalf(template string, args ...interface{})The "f" methods use fmt.Sprintf formatting:
sugar.Infof("User %s logged in from %s", username, ipAddress)func (s *SugaredLogger) Debug(args ...interface{})
func (s *SugaredLogger) Info(args ...interface{})
func (s *SugaredLogger) Warn(args ...interface{})
func (s *SugaredLogger) Error(args ...interface{})
func (s *SugaredLogger) DPanic(args ...interface{})
func (s *SugaredLogger) Panic(args ...interface{})
func (s *SugaredLogger) Fatal(args ...interface{})The base methods use fmt.Sprint formatting:
sugar.Info("User logged in:", username, ipAddress)func (s *SugaredLogger) Debugln(args ...interface{})
func (s *SugaredLogger) Infoln(args ...interface{})
func (s *SugaredLogger) Warnln(args ...interface{})
func (s *SugaredLogger) Errorln(args ...interface{})
func (s *SugaredLogger) DPanicln(args ...interface{})
func (s *SugaredLogger) Panicln(args ...interface{})
func (s *SugaredLogger) Fatalln(args ...interface{})func (s *SugaredLogger) Log(lvl zapcore.Level, args ...interface{})
func (s *SugaredLogger) Logf(lvl zapcore.Level, template string, args ...interface{})
func (s *SugaredLogger) Logw(lvl zapcore.Level, msg string, keysAndValues ...interface{})
func (s *SugaredLogger) Logln(lvl zapcore.Level, args ...interface{})func (s *SugaredLogger) With(args ...interface{}) *SugaredLogger
func (s *SugaredLogger) WithLazy(args ...interface{}) *SugaredLogger
func (s *SugaredLogger) Named(name string) *SugaredLogger
func (s *SugaredLogger) WithOptions(opts ...Option) *SugaredLoggerThe With methods accept either alternating key-value pairs or strongly-typed Field values:
// Key-value pairs
contextSugar := sugar.With("request_id", reqID, "user_id", userID)
// Strongly-typed fields
contextSugar := sugar.With(zap.String("request_id", reqID))func (s *SugaredLogger) Desugar() *Logger
func (s *SugaredLogger) Sync() errorfunc (s *SugaredLogger) Level() zapcore.LevelGet minimum enabled log level.
sugar := logger.Sugar()
defer sugar.Sync()
sugar.Infow("user action",
"action", "login",
"username", "alice",
"ip", "192.168.1.100",
"timestamp", time.Now(),
)
sugar.Errorw("request failed",
"method", "GET",
"url", "/api/users",
"status", 500,
"error", err.Error(),
)sugar.Infof("User %s logged in from %s at %v", username, ip, timestamp)
sugar.Errorf("Failed to connect to %s:%d - %v", host, port, err)requestSugar := sugar.With(
"request_id", requestID,
"user_id", userID,
)
requestSugar.Info("starting request processing")
requestSugar.Warn("slow database query")logger, _ := zap.NewProduction()
// Convert to SugaredLogger for convenience
sugar := logger.Sugar()
sugar.Infow("using sugared logger", "convenient", true)
// Convert back to Logger for performance
fastLogger := sugar.Desugar()
fastLogger.Info("using fast logger", zap.Bool("fast", true))Use Logger when:
Use SugaredLogger when:
Performance comparison: