or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

configuration.mdfields.mdindex.mdintegrations.mdlogger.mdtesting.mdzapcore.md
tile.json

logger.mddocs/

Logger and SugaredLogger

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.

Logger - High Performance, Strongly-Typed

The Logger type provides strongly-typed, zero-allocation logging for performance-critical code paths. All context fields must be explicitly typed using field constructors.

Logger Type

type Logger struct {
    // unexported fields
}

Core Logging Methods

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)
  • Debug: Debug-level logs (typically voluminous, disabled in production)
  • Info: Info-level logs (default logging priority)
  • Warn: Warning-level logs (more important than Info)
  • Error: Error-level logs (high priority)
  • DPanic: Development panic (panics in development mode, logs in production)
  • Panic: Logs message then panics
  • Fatal: Logs message then calls os.Exit(1)

Generic Logging Method

func (log *Logger) Log(lvl zapcore.Level, msg string, fields ...Field)

Log at a specific level dynamically.

Context Management

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) *Logger
  • With: Create child logger with added context fields (evaluated immediately)
  • WithLazy: Create child logger with lazily-evaluated context fields
  • Named: Add a name segment to the logger (useful for identifying subsystems)
  • WithOptions: Clone logger with additional options

Logger Conversion and Control

func (log *Logger) Sugar() *SugaredLogger
func (log *Logger) Sync() error
  • Sugar: Convert to SugaredLogger for more flexible API
  • Sync: Flush any buffered log entries (call before program exit)

Introspection

func (log *Logger) Core() zapcore.Core
func (log *Logger) Name() string
func (log *Logger) Level() zapcore.Level
  • Core: Access underlying zapcore.Core
  • Name: Get logger name
  • Level: Get minimum enabled log level

Level Checking

func (log *Logger) Check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry

Check if a level is enabled and prepare an entry for writing. Useful for avoiding expensive field computation when logging is disabled.

Usage Examples

Basic Logging

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),
)

Creating Child Loggers with Context

// 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")

Named Loggers for Subsystems

authLogger := logger.Named("auth")
dbLogger := logger.Named("database")

authLogger.Info("authentication successful")  // logged as "auth"
dbLogger.Error("query timeout")                // logged as "database"

Conditional Logging with Check

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()),
    )
}

SugaredLogger - Convenient, Loosely-Typed

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.

SugaredLogger Type

type SugaredLogger struct {
    // unexported fields
}

Structured Logging (Key-Value Pairs)

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,
)

Printf-Style Logging

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)

Variadic Logging

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)

Println-Style Logging

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{})

Generic Logging Methods

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{})

Context Management

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) *SugaredLogger

The 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))

Logger Conversion and Control

func (s *SugaredLogger) Desugar() *Logger
func (s *SugaredLogger) Sync() error
  • Desugar: Convert to strongly-typed Logger for performance-critical code
  • Sync: Flush any buffered log entries

Introspection

func (s *SugaredLogger) Level() zapcore.Level

Get minimum enabled log level.

Usage Examples

Structured Logging with Key-Value Pairs

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(),
)

Printf-Style Logging

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)

Adding Context

requestSugar := sugar.With(
    "request_id", requestID,
    "user_id", userID,
)

requestSugar.Info("starting request processing")
requestSugar.Warn("slow database query")

Converting Between Logger Types

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))

Choosing Between Logger and SugaredLogger

Use Logger when:

  • Performance is critical (hot path, high-frequency logging)
  • Every allocation matters
  • You need zero-allocation logging
  • Code clarity benefits from explicit types

Use SugaredLogger when:

  • Convenience is more important than raw performance
  • You prefer Printf-style formatting
  • You're migrating from another logging library
  • Logging is not in a hot path

Performance comparison:

  • Logger: Fastest, zero-allocation for most operations
  • SugaredLogger: Still 4-10x faster than other structured logging libraries
  • Conversion between types is cheap and safe