Problem Statement
Replace fmt.Printf with production-grade structured logging using Zap, the high-performance logger used by Uber.
Replace fmt.Printf with production-grade structured logging using Zap, the high-performance logger used by Uber.
// ❌ 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"}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()
}// 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,
)// 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)")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()),
)
}
}// ❌ 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"),
)