slog

Structured, contextual, extensible, composable logging library for Rust. Designed to be superset of standard log crate. Composition is strong selling point of slog, enabling flexible logger construction.

LoggingGoStructured LoggingStandard Library

Library

slog

Overview

slog is "a structured logging library for Go" that was added to the standard library in Go 1.21 as a modern logging solution. With the concept of "machine-readable logs," it moves away from traditional text-based logging to provide structured logs in key-value pair format. Through high-performance and type-safe logging functionality, it efficiently handles log analysis, search, and aggregation, establishing itself as the next-generation logging standard for improving observability in large-scale applications.

Details

slog 2025 edition has established a solid position as the definitive structured logging solution in the Go ecosystem. With integration into the standard library from Go 1.21, it achieves enterprise-level logging functionality without third-party dependencies. It provides comprehensive logging features required in modern microservice environments including clear log level control with DEBUG, INFO, WARN, ERROR levels, flexible output format support through custom handlers, and automatic integration of context information.

Key Features

  • Structured Logging: Machine-readable logs in key-value pair format
  • High-Performance Design: Zero-allocation optimization and lazy evaluation
  • Flexible Handlers: Support for Text, JSON, and custom output formats
  • Type Safety: Safe log recording using Go's type system
  • Context Integration: Complete integration with context.Context
  • Dynamic Level Control: Runtime log level modification functionality

Pros and Cons

Pros

  • Stability and long-term support guarantee as Go standard library
  • Enterprise-level structured logging functionality without third-party dependencies
  • Low overhead operation in production environments through high-performance design
  • Intuitive and consistent API design following Go language conventions
  • Rich output options and extensibility with JSON and text formats
  • Microservice support through natural integration with context.Context
  • Flexible extension and customization through custom handlers

Cons

  • Only available in Go 1.21 and later (not available in older Go versions)
  • Feature limitations compared to mature third-party libraries (zap, logrus, etc.)
  • Lack of advanced features like log rotation, filtering, and transformation
  • Learning cost and compatibility issues when migrating existing projects
  • No standard provision of large-scale log management or archive features
  • Need for compatibility adjustments with some ecosystem libraries

Reference Pages

Code Examples

Installation and Setup (Import Only as Standard Library)

package main

import (
    "log/slog"
    "os"
    "context"
    "time"
)

func main() {
    // Most basic setup (default handler)
    // TextHandler is automatically used
    slog.Info("application started")
    
    // Initialization with custom handler
    logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
    slog.SetDefault(logger)
    
    // Handler with configuration options
    options := &slog.HandlerOptions{
        Level:     slog.LevelDebug,    // Output from debug level
        AddSource: true,               // Add source file information
        ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
            // Customize timestamp format
            if a.Key == slog.TimeKey {
                return slog.String("timestamp", a.Value.Time().Format(time.RFC3339))
            }
            return a
        },
    }
    
    textHandler := slog.NewTextHandler(os.Stdout, options)
    customLogger := slog.New(textHandler)
    
    customLogger.Info("custom handler initialization complete",
        "handler_type", "TextHandler",
        "debug_enabled", true,
        "source_enabled", true,
    )
}

Basic Log Output

package main

import (
    "log/slog"
    "os"
    "time"
    "errors"
)

func main() {
    // Basic setup with JSON handler
    logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
        Level: slog.LevelDebug,
    }))
    slog.SetDefault(logger)
    
    // Basic log level usage
    slog.Debug("detailed debug information", "function", "main", "step", 1)
    slog.Info("general information", "app_name", "example_app", "version", "1.0.0")
    slog.Warn("warning message", "config_missing", true, "using_defaults", true)
    slog.Error("error occurred", "error", errors.New("sample error"), "critical", false)
    
    // Structured logging with key-value pairs
    slog.Info("user action",
        "user_id", 12345,
        "action", "login",
        "ip_address", "192.168.1.100",
        "user_agent", "Mozilla/5.0...",
        "timestamp", time.Now(),
        "success", true,
    )
    
    // Example using different data types
    slog.Info("data type samples",
        "string_value", "Hello, World!",
        "int_value", 42,
        "float_value", 3.14159,
        "bool_value", true,
        "time_value", time.Now(),
        "duration_value", 250*time.Millisecond,
        "slice_value", []string{"apple", "banana", "cherry"},
        "map_value", map[string]int{"red": 1, "green": 2, "blue": 3},
    )
    
    // Error handling and logging
    err := performOperation()
    if err != nil {
        slog.Error("operation failed",
            "operation", "data_processing",
            "error", err,
            "retry_count", 3,
            "fatal", false,
        )
    } else {
        slog.Info("operation succeeded",
            "operation", "data_processing",
            "duration", "150ms",
            "items_processed", 1000,
        )
    }
}

func performOperation() error {
    // Simulation of some process
    return nil // or errors.New("processing error")
}

Structured Logging (Key-Value Pairs)

package main

import (
    "log/slog"
    "os"
    "time"
    "context"
)

func main() {
    // Output in JSON format
    logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
    slog.SetDefault(logger)
    
    // Type-safe structured logging using slog.Attr
    slog.Info("HTTP request details",
        slog.String("method", "POST"),
        slog.String("endpoint", "/api/v1/users"),
        slog.Int("status_code", 201),
        slog.Duration("response_time", 120*time.Millisecond),
        slog.Int64("request_size", 1024),
        slog.Int64("response_size", 512),
        slog.Bool("authenticated", true),
    )
    
    // Hierarchical log structure using Group
    slog.Info("database operation",
        slog.Group("database",
            slog.String("driver", "postgres"),
            slog.String("host", "localhost"),
            slog.Int("port", 5432),
            slog.String("database", "myapp"),
        ),
        slog.Group("query",
            slog.String("operation", "SELECT"),
            slog.String("table", "users"),
            slog.String("conditions", "WHERE active = true"),
            slog.Int("limit", 100),
        ),
        slog.Group("performance",
            slog.Duration("execution_time", 45*time.Millisecond),
            slog.Int("rows_returned", 85),
            slog.Bool("cache_hit", false),
        ),
    )
    
    // Logging complex data structures
    requestData := map[string]interface{}{
        "headers": map[string]string{
            "Content-Type":  "application/json",
            "Authorization": "Bearer <redacted>",
            "User-Agent":   "MyApp/1.0",
        },
        "payload": map[string]interface{}{
            "username": "user123",
            "email":    "[email protected]",
            "settings": map[string]bool{
                "notifications": true,
                "marketing":    false,
            },
        },
    }
    
    slog.Info("API call",
        "endpoint", "/api/users",
        "method", "POST",
        slog.Group("request",
            slog.Any("headers", requestData["headers"]),
            slog.Any("payload", requestData["payload"]),
        ),
        slog.Group("metadata",
            slog.String("trace_id", "abc123def456"),
            slog.String("span_id", "789xyz"),
            slog.Time("started_at", time.Now()),
        ),
    )
    
    // Business logic specific logging
    order := struct {
        ID       string    `json:"id"`
        UserID   int       `json:"user_id"`
        Total    float64   `json:"total"`
        Items    int       `json:"items"`
        Created  time.Time `json:"created"`
        Shipping string    `json:"shipping"`
    }{
        ID:       "ORD-2024-001",
        UserID:   12345,
        Total:    99.99,
        Items:    3,
        Created:  time.Now(),
        Shipping: "express",
    }
    
    slog.Info("order processing",
        slog.Group("order",
            slog.String("order_id", order.ID),
            slog.Int("user_id", order.UserID),
            slog.Float64("total_amount", order.Total),
            slog.Int("item_count", order.Items),
            slog.Time("created_at", order.Created),
            slog.String("shipping_method", order.Shipping),
        ),
        slog.Group("processing",
            slog.String("status", "completed"),
            slog.Duration("processing_time", 2*time.Second),
            slog.Bool("payment_verified", true),
            slog.Bool("inventory_updated", true),
        ),
    )
}

Custom Logger Creation

package main

import (
    "context"
    "log/slog"
    "os"
    "io"
    "fmt"
    "strings"
    "time"
)

// Application-specific custom logger
type AppLogger struct {
    *slog.Logger
    appName    string
    version    string
    instanceID string
}

// Create custom logger
func NewAppLogger(appName, version, instanceID string, handler slog.Handler) *AppLogger {
    // Create logger with common attributes
    baseLogger := slog.New(handler).With(
        "app_name", appName,
        "app_version", version,
        "instance_id", instanceID,
    )
    
    return &AppLogger{
        Logger:     baseLogger,
        appName:    appName,
        version:    version,
        instanceID: instanceID,
    }
}

// Log method for business logic
func (al *AppLogger) LogUserAction(ctx context.Context, userID int, action string, details map[string]interface{}) {
    attrs := []slog.Attr{
        slog.Int("user_id", userID),
        slog.String("action", action),
        slog.Time("timestamp", time.Now()),
    }
    
    if details != nil {
        detailAttrs := make([]slog.Attr, 0, len(details))
        for k, v := range details {
            detailAttrs = append(detailAttrs, slog.Any(k, v))
        }
        attrs = append(attrs, slog.Group("details", detailAttrs...))
    }
    
    al.Logger.LogAttrs(ctx, slog.LevelInfo, "user action", attrs...)
}

func (al *AppLogger) LogAPICall(ctx context.Context, method, endpoint string, statusCode int, duration time.Duration) {
    level := slog.LevelInfo
    if statusCode >= 400 {
        level = slog.LevelWarn
    }
    if statusCode >= 500 {
        level = slog.LevelError
    }
    
    al.Logger.LogAttrs(ctx, level, "API call",
        slog.String("http_method", method),
        slog.String("endpoint", endpoint),
        slog.Int("status_code", statusCode),
        slog.Duration("response_time", duration),
        slog.Group("classification",
            slog.Bool("success", statusCode < 400),
            slog.Bool("client_error", statusCode >= 400 && statusCode < 500),
            slog.Bool("server_error", statusCode >= 500),
        ),
    )
}

func (al *AppLogger) LogError(ctx context.Context, err error, operation string, metadata map[string]interface{}) {
    attrs := []slog.Attr{
        slog.String("error", err.Error()),
        slog.String("operation", operation),
    }
    
    if metadata != nil {
        metaAttrs := make([]slog.Attr, 0, len(metadata))
        for k, v := range metadata {
            metaAttrs = append(metaAttrs, slog.Any(k, v))
        }
        attrs = append(attrs, slog.Group("metadata", metaAttrs...))
    }
    
    al.Logger.LogAttrs(ctx, slog.LevelError, "error occurred", attrs...)
}

// Custom handler: output in specific format
type CustomFormatHandler struct {
    writer io.Writer
    level  slog.Level
}

func NewCustomFormatHandler(w io.Writer, level slog.Level) *CustomFormatHandler {
    return &CustomFormatHandler{writer: w, level: level}
}

func (h *CustomFormatHandler) Enabled(ctx context.Context, level slog.Level) bool {
    return level >= h.level
}

func (h *CustomFormatHandler) Handle(ctx context.Context, r slog.Record) error {
    // Custom format: [TIME] LEVEL APP_NAME: MESSAGE key1=value1 key2=value2
    var builder strings.Builder
    
    builder.WriteString("[")
    builder.WriteString(r.Time.Format("2006-01-02 15:04:05"))
    builder.WriteString("] ")
    builder.WriteString(r.Level.String())
    builder.WriteString(" ")
    
    // Get app information
    appName := "unknown"
    r.Attrs(func(a slog.Attr) bool {
        if a.Key == "app_name" {
            appName = a.Value.String()
        }
        return true
    })
    
    builder.WriteString(appName)
    builder.WriteString(": ")
    builder.WriteString(r.Message)
    
    // Add attributes in key=value format
    r.Attrs(func(a slog.Attr) bool {
        if a.Key != "app_name" && a.Key != "app_version" && a.Key != "instance_id" {
            builder.WriteString(" ")
            builder.WriteString(a.Key)
            builder.WriteString("=")
            builder.WriteString(fmt.Sprintf("%v", a.Value.Any()))
        }
        return true
    })
    
    builder.WriteString("\n")
    _, err := h.writer.Write([]byte(builder.String()))
    return err
}

func (h *CustomFormatHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
    // For simplicity, return a new handler instance
    return h
}

func (h *CustomFormatHandler) WithGroup(name string) slog.Handler {
    // For simplicity, return the same handler
    return h
}

func main() {
    // Example with standard JSON handler
    jsonHandler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
        Level:     slog.LevelDebug,
        AddSource: false,
    })
    
    appLogger1 := NewAppLogger("MyWebApp", "1.2.3", "inst-001", jsonHandler)
    
    ctx := context.Background()
    
    // Using business logic log methods
    appLogger1.LogUserAction(ctx, 12345, "login", map[string]interface{}{
        "ip_address": "192.168.1.100",
        "user_agent": "Mozilla/5.0...",
        "method":     "oauth2",
    })
    
    appLogger1.LogAPICall(ctx, "GET", "/api/users/12345", 200, 150*time.Millisecond)
    appLogger1.LogAPICall(ctx, "POST", "/api/orders", 400, 50*time.Millisecond)
    appLogger1.LogAPICall(ctx, "GET", "/api/reports", 500, 2*time.Second)
    
    // Error logging example
    err := fmt.Errorf("database connection error")
    appLogger1.LogError(ctx, err, "user_data_fetch", map[string]interface{}{
        "user_id":    12345,
        "retry_count": 3,
        "timeout":    "30s",
    })
    
    fmt.Println("\n--- Custom Format Handler ---")
    
    // Example with custom format handler
    customHandler := NewCustomFormatHandler(os.Stdout, slog.LevelInfo)
    appLogger2 := NewAppLogger("CustomApp", "2.0.0", "inst-002", customHandler)
    
    appLogger2.Info("application started")
    appLogger2.LogUserAction(ctx, 67890, "purchase", map[string]interface{}{
        "amount":   99.99,
        "currency": "USD",
        "items":    3,
    })
    
    // Regular slog methods are also available
    appLogger2.Logger.Warn("high memory usage",
        "memory_usage_mb", 1024,
        "threshold_mb", 800,
        "action_required", true,
    )
}

Handler Configuration

package main

import (
    "context"
    "fmt"
    "log/slog"
    "os"
    "strings"
    "time"
    "sync"
    "path/filepath"
)

// Multi-output handler: simultaneous output to multiple destinations
type MultiHandler struct {
    handlers []slog.Handler
}

func NewMultiHandler(handlers ...slog.Handler) *MultiHandler {
    return &MultiHandler{handlers: handlers}
}

func (h *MultiHandler) Enabled(ctx context.Context, level slog.Level) bool {
    for _, handler := range h.handlers {
        if handler.Enabled(ctx, level) {
            return true
        }
    }
    return false
}

func (h *MultiHandler) Handle(ctx context.Context, r slog.Record) error {
    for _, handler := range h.handlers {
        if handler.Enabled(ctx, r.Level) {
            if err := handler.Handle(ctx, r); err != nil {
                return err
            }
        }
    }
    return nil
}

func (h *MultiHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
    newHandlers := make([]slog.Handler, len(h.handlers))
    for i, handler := range h.handlers {
        newHandlers[i] = handler.WithAttrs(attrs)
    }
    return &MultiHandler{handlers: newHandlers}
}

func (h *MultiHandler) WithGroup(name string) slog.Handler {
    newHandlers := make([]slog.Handler, len(h.handlers))
    for i, handler := range h.handlers {
        newHandlers[i] = handler.WithGroup(name)
    }
    return &MultiHandler{handlers: newHandlers}
}

// Level-based file output handler
type LevelFileHandler struct {
    mu           sync.Mutex
    files        map[slog.Level]*os.File
    baseHandler  slog.Handler
}

func NewLevelFileHandler(baseDir string) (*LevelFileHandler, error) {
    if err := os.MkdirAll(baseDir, 0755); err != nil {
        return nil, err
    }
    
    handler := &LevelFileHandler{
        files: make(map[slog.Level]*os.File),
    }
    
    levels := []slog.Level{slog.LevelDebug, slog.LevelInfo, slog.LevelWarn, slog.LevelError}
    levelNames := []string{"debug", "info", "warn", "error"}
    
    for i, level := range levels {
        filename := filepath.Join(baseDir, fmt.Sprintf("%s.log", levelNames[i]))
        file, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
        if err != nil {
            // Close already opened files
            for _, f := range handler.files {
                f.Close()
            }
            return nil, err
        }
        handler.files[level] = file
    }
    
    // Use JSON format as base handler
    handler.baseHandler = slog.NewJSONHandler(os.Stdout, nil)
    
    return handler, nil
}

func (h *LevelFileHandler) Enabled(ctx context.Context, level slog.Level) bool {
    return true // Enable all levels
}

func (h *LevelFileHandler) Handle(ctx context.Context, r slog.Record) error {
    h.mu.Lock()
    defer h.mu.Unlock()
    
    // Select appropriate file
    var targetFile *os.File
    if r.Level >= slog.LevelError {
        targetFile = h.files[slog.LevelError]
    } else if r.Level >= slog.LevelWarn {
        targetFile = h.files[slog.LevelWarn]
    } else if r.Level >= slog.LevelInfo {
        targetFile = h.files[slog.LevelInfo]
    } else {
        targetFile = h.files[slog.LevelDebug]
    }
    
    if targetFile != nil {
        // Create handler for file
        fileHandler := slog.NewJSONHandler(targetFile, nil)
        fileHandler.Handle(ctx, r)
    }
    
    // Also output to stdout
    return h.baseHandler.Handle(ctx, r)
}

func (h *LevelFileHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
    return &LevelFileHandler{
        files:       h.files,
        baseHandler: h.baseHandler.WithAttrs(attrs),
    }
}

func (h *LevelFileHandler) WithGroup(name string) slog.Handler {
    return &LevelFileHandler{
        files:       h.files,
        baseHandler: h.baseHandler.WithGroup(name),
    }
}

func (h *LevelFileHandler) Close() error {
    h.mu.Lock()
    defer h.mu.Unlock()
    
    for _, file := range h.files {
        if err := file.Close(); err != nil {
            return err
        }
    }
    return nil
}

// Dynamic level control handler
type DynamicLevelHandler struct {
    levelVar *slog.LevelVar
    handler  slog.Handler
}

func NewDynamicLevelHandler(initialLevel slog.Level, handler slog.Handler) *DynamicLevelHandler {
    levelVar := &slog.LevelVar{}
    levelVar.Set(initialLevel)
    
    return &DynamicLevelHandler{
        levelVar: levelVar,
        handler:  handler,
    }
}

func (h *DynamicLevelHandler) Enabled(ctx context.Context, level slog.Level) bool {
    return level >= h.levelVar.Level()
}

func (h *DynamicLevelHandler) Handle(ctx context.Context, r slog.Record) error {
    if !h.Enabled(ctx, r.Level) {
        return nil
    }
    return h.handler.Handle(ctx, r)
}

func (h *DynamicLevelHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
    return &DynamicLevelHandler{
        levelVar: h.levelVar,
        handler:  h.handler.WithAttrs(attrs),
    }
}

func (h *DynamicLevelHandler) WithGroup(name string) slog.Handler {
    return &DynamicLevelHandler{
        levelVar: h.levelVar,
        handler:  h.handler.WithGroup(name),
    }
}

func (h *DynamicLevelHandler) SetLevel(level slog.Level) {
    h.levelVar.Set(level)
}

func (h *DynamicLevelHandler) GetLevel() slog.Level {
    return h.levelVar.Level()
}

func main() {
    fmt.Println("=== Handler Configuration Examples ===")
    
    // 1. Basic handler configuration
    fmt.Println("\n1. Basic JSON Handler:")
    jsonHandler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
        Level:     slog.LevelInfo,
        AddSource: true,
        ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
            // Mask sensitive information
            if a.Key == "password" || a.Key == "token" {
                return slog.String(a.Key, "[REDACTED]")
            }
            // Change timestamp format
            if a.Key == slog.TimeKey {
                return slog.String("timestamp", a.Value.Time().Format("2006-01-02 15:04:05.000"))
            }
            return a
        },
    })
    
    logger1 := slog.New(jsonHandler)
    logger1.Info("user authentication",
        "username", "user123",
        "password", "secret123", // This will be masked
        "token", "jwt-token-abc", // This will also be masked
        "success", true,
    )
    
    // 2. Text handler configuration
    fmt.Println("\n2. Custom Text Handler:")
    textHandler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
        Level:     slog.LevelDebug,
        AddSource: false,
    })
    
    logger2 := slog.New(textHandler)
    logger2.Debug("debug information", "module", "auth", "step", "validation")
    logger2.Info("processing complete", "duration", 150*time.Millisecond)
    
    // 3. Multi-handler usage (multiple output destinations)
    fmt.Println("\n3. Multi-handler (stdout + file):")
    
    // File output handler
    logFile, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
    if err != nil {
        panic(err)
    }
    defer logFile.Close()
    
    fileHandler := slog.NewJSONHandler(logFile, nil)
    consoleHandler := slog.NewTextHandler(os.Stdout, nil)
    
    multiHandler := NewMultiHandler(fileHandler, consoleHandler)
    logger3 := slog.New(multiHandler)
    
    logger3.Info("multi-output test", "destination", "both file and console")
    
    // 4. Level-based file output
    fmt.Println("\n4. Level-based File Output:")
    levelFileHandler, err := NewLevelFileHandler("logs")
    if err != nil {
        panic(err)
    }
    defer levelFileHandler.Close()
    
    logger4 := slog.New(levelFileHandler)
    logger4.Debug("debug message")
    logger4.Info("info message")  
    logger4.Warn("warning message")
    logger4.Error("error message")
    
    // 5. Dynamic level control
    fmt.Println("\n5. Dynamic Level Control:")
    baseHandler := slog.NewTextHandler(os.Stdout, nil)
    dynamicHandler := NewDynamicLevelHandler(slog.LevelInfo, baseHandler)
    logger5 := slog.New(dynamicHandler)
    
    logger5.Debug("debug (not shown)")
    logger5.Info("info (shown)")
    
    // Change level to DEBUG
    dynamicHandler.SetLevel(slog.LevelDebug)
    logger5.Debug("debug (now shown)")
    
    // Change level to ERROR
    dynamicHandler.SetLevel(slog.LevelError)
    logger5.Info("info (not shown)")
    logger5.Error("error (shown)")
    
    // 6. Context-aware handler
    fmt.Println("\n6. Context-aware Handler:")
    
    // Logger with request-specific information
    baseCtxHandler := slog.NewJSONHandler(os.Stdout, nil)
    requestLogger := slog.New(baseCtxHandler).With(
        "request_id", "req-12345",
        "user_id", 67890,
        "session_id", "sess-abcdef",
    )
    
    requestLogger.Info("request started")
    requestLogger.Info("authentication check", "auth_method", "bearer_token")
    requestLogger.Info("data fetch", "table", "users", "rows", 150)
    requestLogger.Info("response sent", "status", 200, "size_bytes", 2048)
    
    fmt.Println("\n=== Log files created ===")
    fmt.Println("- app.log (multi-handler output)")
    fmt.Println("- logs/debug.log (debug level)")
    fmt.Println("- logs/info.log (info level)")
    fmt.Println("- logs/warn.log (warning level)")
    fmt.Println("- logs/error.log (error level)")
}

Performance Optimization

package main

import (
    "context"
    "fmt"
    "log/slog"
    "os"
    "runtime"
    "sync"
    "time"
    "unsafe"
)

// High-performance buffering handler
type BufferedHandler struct {
    mu       sync.Mutex
    handler  slog.Handler
    buffer   []slog.Record
    bufSize  int
    flushInterval time.Duration
    lastFlush     time.Time
}

func NewBufferedHandler(handler slog.Handler, bufSize int, flushInterval time.Duration) *BufferedHandler {
    bh := &BufferedHandler{
        handler:       handler,
        buffer:        make([]slog.Record, 0, bufSize),
        bufSize:       bufSize,
        flushInterval: flushInterval,
        lastFlush:     time.Now(),
    }
    
    // Start periodic flushing
    go bh.periodicFlush()
    
    return bh
}

func (h *BufferedHandler) Enabled(ctx context.Context, level slog.Level) bool {
    return h.handler.Enabled(ctx, level)
}

func (h *BufferedHandler) Handle(ctx context.Context, r slog.Record) error {
    h.mu.Lock()
    defer h.mu.Unlock()
    
    h.buffer = append(h.buffer, r)
    
    // Flush when buffer is full
    if len(h.buffer) >= h.bufSize {
        return h.flushLocked(ctx)
    }
    
    return nil
}

func (h *BufferedHandler) flushLocked(ctx context.Context) error {
    for _, record := range h.buffer {
        if err := h.handler.Handle(ctx, record); err != nil {
            return err
        }
    }
    h.buffer = h.buffer[:0] // Clear buffer
    h.lastFlush = time.Now()
    return nil
}

func (h *BufferedHandler) periodicFlush() {
    ticker := time.NewTicker(h.flushInterval)
    defer ticker.Stop()
    
    for range ticker.C {
        h.mu.Lock()
        if len(h.buffer) > 0 && time.Since(h.lastFlush) >= h.flushInterval {
            h.flushLocked(context.Background())
        }
        h.mu.Unlock()
    }
}

func (h *BufferedHandler) Flush() error {
    h.mu.Lock()
    defer h.mu.Unlock()
    return h.flushLocked(context.Background())
}

func (h *BufferedHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
    return &BufferedHandler{
        handler:       h.handler.WithAttrs(attrs),
        buffer:        make([]slog.Record, 0, h.bufSize),
        bufSize:       h.bufSize,
        flushInterval: h.flushInterval,
        lastFlush:     time.Now(),
    }
}

func (h *BufferedHandler) WithGroup(name string) slog.Handler {
    return &BufferedHandler{
        handler:       h.handler.WithGroup(name),
        buffer:        make([]slog.Record, 0, h.bufSize),
        bufSize:       h.bufSize,
        flushInterval: h.flushInterval,
        lastFlush:     time.Now(),
    }
}

// Zero-allocation optimization example
func optimizedLoggingExample() {
    fmt.Println("=== Zero-allocation Optimization ===")
    
    // Prepare attributes in advance to reduce allocations
    attrs := []slog.Attr{
        slog.String("service", "web-api"),
        slog.String("version", "1.0.0"),
        slog.String("environment", "production"),
    }
    
    handler := slog.NewJSONHandler(os.Stdout, nil)
    logger := slog.New(handler).With(attrs...)
    
    // Optimized logging using LogAttrs
    ctx := context.Background()
    logger.LogAttrs(ctx, slog.LevelInfo, "optimized logging",
        slog.Int("user_id", 12345),
        slog.String("action", "login"),
        slog.Duration("elapsed", 100*time.Millisecond),
    )
    
    // Conditional logging to avoid unnecessary processing
    if logger.Enabled(ctx, slog.LevelDebug) {
        // Heavy processing only when debug level is enabled
        expensiveData := gatherExpensiveDebugData()
        logger.LogAttrs(ctx, slog.LevelDebug, "detailed debug information",
            slog.Any("debug_data", expensiveData),
        )
    }
}

func gatherExpensiveDebugData() map[string]interface{} {
    // Simulation of heavy processing
    time.Sleep(10 * time.Millisecond)
    return map[string]interface{}{
        "memory_stats": runtime.MemStats{},
        "goroutines":   runtime.NumGoroutine(),
        "cpu_count":    runtime.NumCPU(),
    }
}

// Performance test
func performanceTest() {
    fmt.Println("\n=== Performance Test ===")
    
    // Test configuration
    iterations := 100000
    
    // 1. Standard handler test
    jsonHandler := slog.NewJSONHandler(os.Stdout, nil)
    standardLogger := slog.New(jsonHandler)
    
    var m1, m2 runtime.MemStats
    runtime.GC()
    runtime.ReadMemStats(&m1)
    
    start := time.Now()
    for i := 0; i < iterations; i++ {
        standardLogger.Info("test message",
            "iteration", i,
            "timestamp", time.Now().Unix(),
        )
    }
    standardDuration := time.Since(start)
    
    runtime.GC()
    runtime.ReadMemStats(&m2)
    
    fmt.Printf("Standard handler:\n")
    fmt.Printf("  Time: %v (%v ns/op)\n", 
        standardDuration, standardDuration.Nanoseconds()/int64(iterations))
    fmt.Printf("  Memory: %d bytes allocated\n", m2.TotalAlloc-m1.TotalAlloc)
    
    // 2. Buffering handler test
    bufferedHandler := NewBufferedHandler(
        slog.NewJSONHandler(os.Stdout, nil),
        1000, // Buffer size
        100*time.Millisecond, // Flush interval
    )
    bufferedLogger := slog.New(bufferedHandler)
    
    runtime.GC()
    runtime.ReadMemStats(&m1)
    
    start = time.Now()
    for i := 0; i < iterations; i++ {
        bufferedLogger.Info("test message",
            "iteration", i,
            "timestamp", time.Now().Unix(),
        )
    }
    bufferedHandler.Flush() // Explicit flush
    bufferedDuration := time.Since(start)
    
    runtime.GC()
    runtime.ReadMemStats(&m2)
    
    fmt.Printf("Buffering handler:\n")
    fmt.Printf("  Time: %v (%v ns/op)\n", 
        bufferedDuration, bufferedDuration.Nanoseconds()/int64(iterations))
    fmt.Printf("  Memory: %d bytes allocated\n", m2.TotalAlloc-m1.TotalAlloc)
    fmt.Printf("  Improvement: %.2fx faster\n", 
        float64(standardDuration)/float64(bufferedDuration))
}

// Concurrent logging test
func concurrentLoggingTest() {
    fmt.Println("\n=== Concurrent Logging Test ===")
    
    handler := slog.NewJSONHandler(os.Stdout, nil)
    logger := slog.New(handler)
    
    var wg sync.WaitGroup
    goroutines := 10
    messagesPerGoroutine := 1000
    
    start := time.Now()
    
    for i := 0; i < goroutines; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            
            for j := 0; j < messagesPerGoroutine; j++ {
                logger.Info("concurrent message",
                    "goroutine", id,
                    "message", j,
                    "thread_safe", true,
                )
            }
        }(i)
    }
    
    wg.Wait()
    duration := time.Since(start)
    
    totalMessages := goroutines * messagesPerGoroutine
    fmt.Printf("Concurrent logging: %d goroutines × %d messages = %d total\n",
        goroutines, messagesPerGoroutine, totalMessages)
    fmt.Printf("Execution time: %v (%v ns/message)\n",
        duration, duration.Nanoseconds()/int64(totalMessages))
}

// Memory efficiency test
func memoryEfficiencyTest() {
    fmt.Println("\n=== Memory Efficiency Test ===")
    
    // Large object logging
    largeData := make([]map[string]interface{}, 1000)
    for i := range largeData {
        largeData[i] = map[string]interface{}{
            "id":    i,
            "name":  fmt.Sprintf("item_%d", i),
            "value": float64(i) * 3.14159,
            "tags":  []string{"tag1", "tag2", "tag3"},
        }
    }
    
    handler := slog.NewJSONHandler(os.Stdout, nil)
    logger := slog.New(handler)
    
    var m1, m2 runtime.MemStats
    runtime.GC()
    runtime.ReadMemStats(&m1)
    
    // Inefficient method (serialize large object every time)
    start := time.Now()
    for i := 0; i < 100; i++ {
        logger.Info("large data", "data", largeData)
    }
    inefficientDuration := time.Since(start)
    
    runtime.GC()
    runtime.ReadMemStats(&m2)
    inefficientMemory := m2.TotalAlloc - m1.TotalAlloc
    
    // Efficient method (log metadata only)
    runtime.GC()
    runtime.ReadMemStats(&m1)
    
    start = time.Now()
    for i := 0; i < 100; i++ {
        logger.Info("large data (metadata only)",
            "data_size", len(largeData),
            "sample_id", largeData[0]["id"],
            "sample_name", largeData[0]["name"],
            "total_memory", unsafe.Sizeof(largeData),
        )
    }
    efficientDuration := time.Since(start)
    
    runtime.GC()
    runtime.ReadMemStats(&m2)
    efficientMemory := m2.TotalAlloc - m1.TotalAlloc
    
    fmt.Printf("Inefficient logging:\n")
    fmt.Printf("  Time: %v\n", inefficientDuration)
    fmt.Printf("  Memory: %d bytes\n", inefficientMemory)
    fmt.Printf("Efficient logging:\n")
    fmt.Printf("  Time: %v\n", efficientDuration)
    fmt.Printf("  Memory: %d bytes\n", efficientMemory)
    fmt.Printf("Improvement:\n")
    fmt.Printf("  Time: %.2fx faster\n", 
        float64(inefficientDuration)/float64(efficientDuration))
    fmt.Printf("  Memory: %.2fx less\n", 
        float64(inefficientMemory)/float64(efficientMemory))
}

func main() {
    optimizedLoggingExample()
    performanceTest()
    concurrentLoggingTest()
    memoryEfficiencyTest()
    
    fmt.Println("\n=== Performance Test Complete ===")
}