日志配置
本示例演示 Fox 中的各种日志配置,从开发友好的控制台日志到生产就绪的文件日志及轮转。
- 控制台日志
- 带轮转的文件日志
- 控制台和文件组合日志
- JSON 格式日志
- 不同的日志级别(Debug、Info、Warn、Error、Fatal、Panic)
- 结构化日志
- 跳过路径配置
- 生产就绪配置
package main
import ( "os"
"github.com/fox-gonic/fox" "github.com/fox-gonic/fox/logger")
func main() { // 示例 1: 仅控制台日志(默认) example1ConsoleOnly()
// 示例 2: 带轮转的文件日志 example2FileLogging()
// 示例 3: 控制台和文件日志 example3BothOutputs()
// 示例 4: JSON 格式日志 example4JSONLogs()
// 示例 5: 不同的日志级别 example5LogLevels()}
// 示例 1: 仅控制台日志(开发模式)func example1ConsoleOnly() { logger.SetConfig(&logger.Config{ LogLevel: logger.InfoLevel, ConsoleLoggingEnabled: true, EncodeLogsAsJSON: false, // 人类可读格式 })
router := fox.New() router.Use(fox.Logger())
router.GET("/console", func(ctx *fox.Context) string { log := logger.NewWithContext(ctx.Context) log.Info("Processing console logging request") log.Debug("This is a debug message (won't show at Info level)") return "Check console for logs" })
// 取消注释以运行 // router.Run(":8080")}
// 示例 2: 带轮转的文件日志func example2FileLogging() { logger.SetConfig(&logger.Config{ LogLevel: logger.InfoLevel, ConsoleLoggingEnabled: false, FileLoggingEnabled: true, Filename: "./logs/app.log", MaxSize: 10, // 兆字节 MaxBackups: 3, // 备份数量 MaxAge: 7, // 天数 EncodeLogsAsJSON: false, })
router := fox.New() router.Use(fox.Logger())
router.GET("/file", func(ctx *fox.Context) string { log := logger.NewWithContext(ctx.Context) log.Info("This will be written to file") return "Check ./logs/app.log for logs" })
// 取消注释以运行 // router.Run(":8081")}
// 示例 3: 控制台和文件日志(生产模式)func example3BothOutputs() { logger.SetConfig(&logger.Config{ LogLevel: logger.InfoLevel, ConsoleLoggingEnabled: true, FileLoggingEnabled: true, Filename: "./logs/production.log", MaxSize: 50, // 轮转前 50MB MaxBackups: 10, // 保留 10 个备份文件 MaxAge: 30, // 保留日志 30 天 EncodeLogsAsJSON: true, // JSON 格式用于解析 })
router := fox.New() router.Use(fox.Logger())
router.GET("/both", func(ctx *fox.Context) string { log := logger.NewWithContext(ctx.Context) log.Info("Logged to both console and file") return "Check both console and file" })
// 取消注释以运行 // router.Run(":8082")}
// 示例 4: JSON 格式日志(用于日志聚合)func example4JSONLogs() { logger.SetConfig(&logger.Config{ LogLevel: logger.DebugLevel, ConsoleLoggingEnabled: true, EncodeLogsAsJSON: true, // JSON 格式 })
router := fox.New() router.Use(fox.Logger())
router.GET("/json", func(ctx *fox.Context) map[string]any { log := logger.NewWithContext(ctx.Context)
log.Info("User action logged") log.WithFields(map[string]any{ "user_id": 123, "action": "view_profile", }).Info("Structured logging example")
return map[string]any{ "message": "Check console for JSON logs", } })
// 取消注释以运行 // router.Run(":8083")}
// 示例 5: 不同的日志级别func example5LogLevels() { // 设置为 Debug 以查看所有消息 logger.SetConfig(&logger.Config{ LogLevel: logger.DebugLevel, ConsoleLoggingEnabled: true, EncodeLogsAsJSON: false, })
router := fox.New()
// 跳过健康检查端点的日志 router.Use(fox.Logger(fox.LoggerConfig{ SkipPaths: []string{"/health"}, }))
router.GET("/levels", func(ctx *fox.Context) string { log := logger.NewWithContext(ctx.Context)
log.Debug("Debug level - debugging info") log.Info("Info level - general info") log.Warn("Warn level - warning message") log.Error("Error level - error occurred")
return "Check console for different log levels" })
router.GET("/health", func() string { return "OK" // 此端点不会被记录 })
// 取消注释以运行 // router.Run(":8084")}
// 完整的生产示例func productionExample() { // 生产配置 logger.SetConfig(&logger.Config{ LogLevel: logger.InfoLevel, // 生产环境不记录 Debug ConsoleLoggingEnabled: true, FileLoggingEnabled: true, Filename: "/var/log/myapp/app.log", MaxSize: 100, // 100MB MaxBackups: 30, // 保留 30 个备份 MaxAge: 90, // 90 天保留期 EncodeLogsAsJSON: true, // JSON 用于日志聚合(ELK、Splunk 等) })
router := fox.New()
// 全局中间件 router.Use(fox.Logger(fox.LoggerConfig{ SkipPaths: []string{ "/health", "/readiness", "/metrics", }, })) router.Use(fox.NewXResponseTimer())
// 业务路由 router.POST("/api/users", func(ctx *fox.Context) (map[string]any, error) { log := logger.NewWithContext(ctx.Context)
log.Info("Creating new user")
// 带字段的结构化日志 log.WithFields(map[string]any{ "user_id": 123, "user_type": "premium", }).Info("User created successfully")
return map[string]any{ "id": 123, "message": "User created", }, nil })
// 错误日志示例 router.GET("/api/error", func(ctx *fox.Context) (string, error) { log := logger.NewWithContext(ctx.Context)
err := os.ErrNotExist log.WithError(err).Error("File not found")
return "", err })
if err := router.Run(":8080"); err != nil { panic(err) }}go run main.go仅控制台日志,人类可读格式:
logger.SetConfig(&logger.Config{ LogLevel: logger.DebugLevel, ConsoleLoggingEnabled: true, EncodeLogsAsJSON: false,})生产模式(仅控制台)
Section titled “生产模式(仅控制台)”Info 级别,JSON 编码用于日志聚合:
logger.SetConfig(&logger.Config{ LogLevel: logger.InfoLevel, ConsoleLoggingEnabled: true, EncodeLogsAsJSON: true,})生产模式(文件 + 控制台)
Section titled “生产模式(文件 + 控制台)”轮转文件日志和控制台输出:
logger.SetConfig(&logger.Config{ LogLevel: logger.InfoLevel, ConsoleLoggingEnabled: true, FileLoggingEnabled: true, Filename: "./logs/app.log", MaxSize: 100, // 100MB MaxBackups: 30, // 保留 30 个备份 MaxAge: 90, // 90 天 EncodeLogsAsJSON: true,})高流量应用的最小日志:
logger.SetConfig(&logger.Config{ LogLevel: logger.WarnLevel, // 仅警告和错误 ConsoleLoggingEnabled: false, FileLoggingEnabled: true, Filename: "./logs/app.log", EncodeLogsAsJSON: true,})Fox 支持这些日志级别(从低到高):
logger.DebugLevel- 详细的调试信息logger.InfoLevel- 一般信息性消息logger.WarnLevel- 警告消息logger.ErrorLevel- 错误消息logger.FatalLevel- 致命错误(调用 os.Exit(1))logger.PanicLevel- Panic 消息(调用 panic())
向日志消息添加上下文字段:
log := logger.NewWithContext(ctx.Context)
log.WithFields(map[string]any{ "user_id": 123, "action": "login", "ip": "192.168.1.1",}).Info("User logged in")从日志中排除某些端点:
router.Use(fox.Logger(fox.LoggerConfig{ SkipPaths: []string{ "/health", "/readiness", "/metrics", },}))Fox 自动为每个请求添加 TraceID 以便关联:
log := logger.NewWithContext(ctx.Context)// TraceID 自动包含在所有日志消息中log.Info("Processing request")日志使用 lumberjack 自动轮转:
MaxSize- 轮转前的最大大小(兆字节)MaxBackups- 保留的旧日志文件最大数量MaxAge- 保留旧日志文件的最大天数
对于生产环境,使用 JSON 格式配合日志聚合系统:
ELK Stack
Section titled “ELK Stack”logger.SetConfig(&logger.Config{ EncodeLogsAsJSON: true, FileLoggingEnabled: true, Filename: "/var/log/myapp/app.log",})配置 Filebeat 将日志发送到 Elasticsearch。
Splunk
Section titled “Splunk”logger.SetConfig(&logger.Config{ EncodeLogsAsJSON: true, ConsoleLoggingEnabled: true,})配置 Splunk Universal Forwarder 收集日志。
AWS CloudWatch
Section titled “AWS CloudWatch”logger.SetConfig(&logger.Config{ EncodeLogsAsJSON: true, ConsoleLoggingEnabled: true, // CloudWatch 从 stdout 收集})使用 CloudWatch Logs 代理或 ECS 日志驱动。
- 使用结构化日志: 添加上下文字段以提高可搜索性
- 选择适当的日志级别: 开发使用 Debug,生产使用 Info/Warn
- 轮转日志: 配置轮转以防止磁盘空间问题
- 生产使用 JSON: 为日志聚合系统使用 JSON 格式
- 跳过健康检查: 排除健康检查端点以减少噪音
- 包含上下文: 始终使用
logger.NewWithContext(ctx.Context)获取 TraceID - 避免敏感数据: 永远不要记录密码、令牌或个人数据
- 性能: 更高的日志级别(Warn/Error)减少开销