DevPrep
  • Interview Prep
  • Projects
  • Resources
  • Pricing
  • About Us
Submit Question
DevPrep
  • Pricing
  • About Us
Submit Question

Practice

  • JavaScript
  • DSA
  • Machine Coding
  • System Design

Resources

  • Learning Tracks
  • Articles
  • Roadmaps
  • Compare Concepts
  • Glossary
  • Developer Tools
  • All Questions

Company

  • About
  • Pricing

Legal

  • Privacy Policy
  • Terms of Service
DevPrep

© 2026 DevPrep. All rights reserved.

← Back to Questions
EasyTheory

Zap: High-Performance Structured Logging

120 views

Problem Statement

Replace fmt.Printf with production-grade structured logging using Zap, the high-performance logger used by Uber.

Why Structured Logging?

// ❌ BAD: Unstructured (hard to parse)
log.Printf("User %s logged in from %s", user, ip)

// ✅ GOOD: Structured JSON (machine parseable)
logger.Info("user logged in",
    zap.String("user", user),
    zap.String("ip", ip),
)
// Output: {"level":"info","msg":"user logged in","user":"alice","ip":"1.2.3.4"}

Zap Setup

package logger

import (
    "os"
    "go.uber.org/zap"
    "go.uber.org/zap/zapcore"
)

var Log *zap.Logger

func Init(env string) {
    var config zap.Config
    
    if env == "production" {
        config = zap.NewProductionConfig()
        config.EncoderConfig.TimeKey = "timestamp"
        config.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
    } else {
        config = zap.NewDevelopmentConfig()
        config.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
    }
    
    var err error
    Log, err = config.Build()
    if err != nil {
        panic(err)
    }
}

func Sync() {
    Log.Sync()
}

Logging Patterns

// Basic logging
Log.Info("server started", zap.Int("port", 8080))
Log.Error("database connection failed", zap.Error(err))
Log.Debug("processing request", zap.String("path", "/api/users"))

// With fields (reusable context)
requestLogger := Log.With(
    zap.String("request_id", requestID),
    zap.String("user_id", userID),
)
requestLogger.Info("handling request")
requestLogger.Info("request completed")

// Sugared logger (slower but convenient)
sugar := Log.Sugar()
sugar.Infof("User %s logged in", username)
sugar.Infow("request completed",
    "status", 200,
    "latency", 42,
)

Log Levels

// In order of severity:
Log.Debug("verbose debugging info")
Log.Info("normal operations")
Log.Warn("something unexpected")
Log.Error("something failed", zap.Error(err))
Log.DPanic("development panic") // Panics in dev, logs in prod
Log.Panic("critical - will panic")
Log.Fatal("critical - will os.Exit(1)")

HTTP Middleware

func LoggingMiddleware(logger *zap.Logger) gin.HandlerFunc {
    return func(c *gin.Context) {
        start := time.Now()
        path := c.Request.URL.Path
        
        c.Next()
        
        logger.Info("http request",
            zap.String("method", c.Request.Method),
            zap.String("path", path),
            zap.Int("status", c.Writer.Status()),
            zap.Duration("latency", time.Since(start)),
            zap.String("client_ip", c.ClientIP()),
        )
    }
}

Error Logging Best Practices

// ❌ BAD: Error as string
Log.Error("failed: " + err.Error())

// ✅ GOOD: Error as field
Log.Error("database query failed",
    zap.Error(err),
    zap.String("query", query),
    zap.Any("params", params),
)

// Stack traces for debugging
Log.Error("unexpected error",
    zap.Error(err),
    zap.Stack("stack"),
)

Sample Test Cases

Case 1
Input
logger.Info("msg", zap.String("key", "val"))
Expected Output
Structured log with key-value fields
Case 2
Input
zap.NewProduction()
Expected Output
JSON output, info level, sampling enabled

No solutions yet

Be the first to share a solution for this question.

Comments (0)

Sign in to leave a comment.

No comments yet. Be the first to comment.

Stats

Views
120
Likes
0
Solutions
0
Comments
0

Category

Backend Engineering

Languages

Go