Files
sub2api/backend/internal/server/middleware/logger.go
yangjianbo f96acf6e27 fix(ops): 修复日志级别过滤并增强OpenAI错误诊断日志
- 移除 warn 级别下 access info 的强制入库补写,确保运行时日志级别真实生效

- 将 OpenAI fallback matched 与 passthrough 断流提示按需求降级为 info

- 为 codex_cli_only 与 instructions required 场景补充请求诊断字段(含 User-Agent)

- 出于安全考虑移除请求体预览,仅保留 request_body_size 与白名单头信息

- 新增/更新回归测试,覆盖 Forward 入口到日志落库链路
2026-02-13 19:27:07 +08:00

67 lines
1.7 KiB
Go

package middleware
import (
"time"
"github.com/Wei-Shaw/sub2api/internal/pkg/ctxkey"
"github.com/Wei-Shaw/sub2api/internal/pkg/logger"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
// Logger 请求日志中间件
func Logger() gin.HandlerFunc {
return func(c *gin.Context) {
// 开始时间
startTime := time.Now()
// 请求路径
path := c.Request.URL.Path
// 处理请求
c.Next()
// 跳过健康检查等高频探针路径的日志
if path == "/health" || path == "/setup/status" {
return
}
endTime := time.Now()
latency := endTime.Sub(startTime)
method := c.Request.Method
statusCode := c.Writer.Status()
clientIP := c.ClientIP()
protocol := c.Request.Proto
accountID, hasAccountID := c.Request.Context().Value(ctxkey.AccountID).(int64)
platform, _ := c.Request.Context().Value(ctxkey.Platform).(string)
model, _ := c.Request.Context().Value(ctxkey.Model).(string)
fields := []zap.Field{
zap.String("component", "http.access"),
zap.Int("status_code", statusCode),
zap.Int64("latency_ms", latency.Milliseconds()),
zap.String("client_ip", clientIP),
zap.String("protocol", protocol),
zap.String("method", method),
zap.String("path", path),
}
if hasAccountID && accountID > 0 {
fields = append(fields, zap.Int64("account_id", accountID))
}
if platform != "" {
fields = append(fields, zap.String("platform", platform))
}
if model != "" {
fields = append(fields, zap.String("model", model))
}
l := logger.FromContext(c.Request.Context()).With(fields...)
l.Info("http request completed", zap.Time("completed_at", endTime))
if len(c.Errors) > 0 {
l.Warn("http request contains gin errors", zap.String("errors", c.Errors.String()))
}
}
}