这篇文章距离最后更新已过558 天,如果文章内容或图片资源失效,请留言反馈,我会及时处理,谢谢!
官方方法
官方文档
zap三方库
可以更高效的记录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | config := zap.Config{ Level: zap.NewAtomicLevelAt(zap.InfoLevel), // 日志级别 Development: false, // 是否是开发模式 Encoding: "console", // 日志格式:json 或 console OutputPaths: []string{"./gin.log"}, // 日志输出路径 ErrorOutputPaths: []string{"./gin.log"}, // 错误日志输出路径 EncoderConfig: zapcore.EncoderConfig{ TimeKey: "time", LevelKey: "level", NameKey: "logger", // CallerKey: "caller", MessageKey: "msg", StacktraceKey: "stacktrace", LineEnding: zapcore.DefaultLineEnding, EncodeLevel: zapcore.CapitalLevelEncoder, // 将日志级别转换为大写 (INFO, WARN, ERROR) EncodeTime: zapcore.ISO8601TimeEncoder, // 时间格式:ISO8601 EncodeDuration: zapcore.StringDurationEncoder, // 持续时间格式化为字符串 // EncodeCaller: zapcore.ShortCallerEncoder, // 简短文件名 + 行号 EncodeName: zapcore.FullNameEncoder, }, } logger, _ := config.Build() defer logger.Sync() r.Use(GinZap(logger)) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | func GinZap(logger *zap.Logger) gin.HandlerFunc { return func(c *gin.Context) { start := time.Now() // 处理请求 c.Next() // 计算处理时间 latency := time.Since(start) // 记录日志 logger.Info("request", zap.String("method", c.Request.Method), zap.String("path", c.Request.URL.Path), zap.Int("status", c.Writer.Status()), zap.Duration("latency", latency), zap.String("clientIP", c.ClientIP()), zap.String("userAgent", c.Request.UserAgent()), zap.String("error", c.Errors.ByType(gin.ErrorTypePrivate).String()), ) } } |
GPT给出的高并发方案
使用缓冲通道或队列将日志写入操作从主请求处理流程中剥离出来,日志先写入内存队列,再由单独的goroutine异步处理并写入文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | package main import ( "github.com/gin-gonic/gin" "log" "os" "time" "fmt" ) // 日志通道 var logChannel = make(chan string, 1000) // 异步日志写入 func asyncLogWriter() { // 打开日志文件 f, err := os.OpenFile("gin_requests.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { log.Fatalf("无法打开日志文件: %v", err) } defer f.Close() // 监听日志通道 for logMsg := range logChannel { _, err := f.WriteString(logMsg + "\n") if err != nil { log.Printf("写入日志文件失败: %v", err) } } } // 日志记录到通道的中间件 func LoggerToFile() gin.HandlerFunc { return func(c *gin.Context) { // 开始时间 startTime := time.Now() // 处理请求 c.Next() // 结束时间 endTime := time.Now() // 计算处理时间 latencyTime := endTime.Sub(startTime) // 请求方式 reqMethod := c.Request.Method // 请求路由 reqUri := c.Request.RequestURI // 状态码 statusCode := c.Writer.Status() // 请求IP clientIP := c.ClientIP() // 日志格式 logMsg := fmt.Sprintf("%s - %s | %3d | %13v | %15s | %-7s %s", startTime.Format("2006-01-02 15:04:05"), endTime.Format("2006-01-02 15:04:05"), statusCode, latencyTime, clientIP, reqMethod, reqUri, ) // 发送日志到通道 logChannel <- logMsg } } func main() { // 启动异步日志写入goroutine go asyncLogWriter() r := gin.Default() // 使用日志中间件 r.Use(LoggerToFile()) // 一个简单的路由 r.GET("/ping", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "pong", }) }) // 启动Gin服务 r.Run(":8080") } |
不错窝