日志管理:从 log 到 zap

日志是排查问题的第一手段。一个好的日志系统应该:结构化、高性能、可配置、易于检索。 1. 标准库 log 1.1 基础使用 1package main 2 3import ( 4 "log" 5) 6 7func main() { 8 log.Println("This is a log message") 9 log.Printf("User %s logged in", "admin") 10 11 // log.Fatal 会调用 os.Exit(1) 12 // log.Fatal("Fatal error") 13 14 // log.Panic 会触发 panic 15 // log.Panic("Panic error") 16} 1.2 自定义 Logger 1import ( 2 "log" 3 "os" 4) 5 6func main() { 7 // 创建自定义 Logger 8 logger := log.New( 9 os.Stdout, // 输出目标 10 "[MyApp] ", // 前缀 11 log.Ldate|log.Ltime|log.Lshortfile, // 标志 12 ) 13 14 logger.Println("Custom logger message") 15 // 输出:[MyApp] 2025/12/18 10:00:00 main.go:15: Custom logger message 16} 1.3 写入文件 1func main() { 2 file, err := os.OpenFile("app.log", 3 os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) 4 if err != nil { 5 panic(err) 6 } 7 defer file.Close() 8 9 log.SetOutput(file) 10 log.Println("This goes to file") 11} 2. slog:结构化日志 (Go 1.21+) 2.1 基础使用 1import ( 2 "log/slog" 3 "os" 4) 5 6func main() { 7 // 创建 JSON 格式的 Logger 8 logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) 9 10 logger.Info("User logged in", 11 "user_id", 123, 12 "username", "admin", 13 "ip", "192.168.1.1") 14 15 // 输出: 16 // {"time":"2025-12-18T10:00:00Z","level":"INFO","msg":"User logged in","user_id":123,"username":"admin","ip":"192.168.1.1"} 17} 2.2 日志级别 1func main() { 2 logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ 3 Level: slog.LevelInfo, // 只输出 Info 及以上级别 4 })) 5 6 logger.Debug("Debug message") // 不会输出 7 logger.Info("Info message") // 会输出 8 logger.Warn("Warning message") // 会输出 9 logger.Error("Error message") // 会输出 10} 2.3 上下文日志 1func main() { 2 logger := slog.Default() 3 4 // 创建带有固定字段的子 Logger 5 requestLogger := logger.With( 6 "request_id", "abc123", 7 "user_id", 456, 8 ) 9 10 requestLogger.Info("Processing request") 11 requestLogger.Info("Request completed") 12 13 // 两条日志都会自动包含 request_id 和 user_id 14} 3. zap:高性能日志库 3.1 安装 1go get -u go.uber.org/zap 3.2 快速开始 1import ( 2 "go.uber.org/zap" 3) 4 5func main() { 6 // 开发环境:易读的格式 7 logger, _ := zap.NewDevelopment() 8 defer logger.Sync() // 刷新缓冲区 9 10 logger.Info("User logged in", 11 zap.String("username", "admin"), 12 zap.Int("user_id", 123)) 13 14 // 生产环境:JSON 格式 15 prodLogger, _ := zap.NewProduction() 16 defer prodLogger.Sync() 17 18 prodLogger.Info("Server started", 19 zap.String("port", "8080")) 20} 3.3 自定义配置 1func main() { 2 config := zap.NewProductionConfig() 3 4 // 设置日志级别 5 config.Level = zap.NewAtomicLevelAt(zap.InfoLevel) 6 7 // 设置输出路径 8 config.OutputPaths = []string{ 9 "stdout", 10 "./logs/app.log", 11 } 12 13 // 设置错误日志路径 14 config.ErrorOutputPaths = []string{ 15 "stderr", 16 "./logs/error.log", 17 } 18 19 logger, _ := config.Build() 20 defer logger.Sync() 21 22 logger.Info("Application started") 23} 3.4 性能对比 1// zap 提供了 SugaredLogger,牺牲一点性能换取更简洁的 API 2logger, _ := zap.NewProduction() 3sugar := logger.Sugar() 4 5// 结构化日志(最快) 6logger.Info("User logged in", 7 zap.String("username", "admin")) 8 9// 格式化日志(稍慢,但更方便) 10sugar.Infof("User %s logged in", "admin") 4. 日志分级 4.1 日志级别 从低到高: ...

2025-07-18 · 3 min · 617 words · Hank