将所有 log.Printf/Println 调用替换为 logging.Logger 结构化日志输出: - internal/middleware/auth.go: AUTH_WARNING 和 AUTH_ERROR 日志 - internal/middleware/middleware.go: Recovery 中间件 panic 日志 - internal/domain/account.go: emitAudit 审计错误日志 - internal/domain/settlement.go: emitAudit 审计错误日志 - internal/domain/package.go: emitAudit 审计错误日志 - internal/domain/compensation.go: 补偿处理器所有日志 - internal/compensation/compensation.go: 补偿执行器所有日志 - internal/outbox/outbox.go: OutboxProcessor 所有日志 - internal/iam/middleware/scope_auth.go: WILDCARD_SCOPE_ACCESS 审计日志 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
72 lines
2.0 KiB
Go
72 lines
2.0 KiB
Go
package middleware
|
||
|
||
import (
|
||
"fmt"
|
||
"net/http"
|
||
"runtime/debug"
|
||
|
||
"lijiaoqiao/supply-api/internal/pkg/logging"
|
||
)
|
||
|
||
// Recovery 中间件 - 恢复 panic
|
||
func Recovery(next http.Handler) http.Handler {
|
||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
defer func() {
|
||
if err := recover(); err != nil {
|
||
// 使用结构化日志记录 panic
|
||
logger := logging.NewLogger("supply-api", logging.LogLevelError)
|
||
logger.Error("panic recovered", map[string]interface{}{
|
||
"error": fmt.Sprintf("%v", err),
|
||
"stack": string(debug.Stack()),
|
||
"path": r.URL.Path,
|
||
"method": r.Method,
|
||
})
|
||
http.Error(w, "internal server error", http.StatusInternalServerError)
|
||
}
|
||
}()
|
||
next.ServeHTTP(w, r)
|
||
})
|
||
}
|
||
|
||
// Logging 中间件 - 请求日志(使用结构化JSON日志)
|
||
// P1-010修复: 使用结构化日志替代标准log
|
||
func Logging(next http.Handler, logger logging.Logger) http.Handler {
|
||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
// 从context获取追踪信息
|
||
fields := make(map[string]interface{})
|
||
fields["method"] = r.Method
|
||
fields["path"] = r.URL.Path
|
||
fields["query"] = r.URL.RawQuery
|
||
|
||
// 尝试获取request_id
|
||
if requestID := r.Header.Get("X-Request-Id"); requestID != "" {
|
||
fields["request_id"] = requestID
|
||
} else if requestID := r.Header.Get("X-Request-ID"); requestID != "" {
|
||
fields["request_id"] = requestID
|
||
}
|
||
|
||
// 尝试获取trace_id
|
||
if tc, ok := GetTraceContext(r.Context()); ok {
|
||
fields["trace_id"] = tc.TraceID
|
||
fields["span_id"] = tc.SpanID
|
||
}
|
||
|
||
logger.Info("HTTP request", fields)
|
||
next.ServeHTTP(w, r)
|
||
})
|
||
}
|
||
|
||
// RequestID 中间件 - 请求追踪
|
||
func RequestID(next http.Handler) http.Handler {
|
||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
requestID := r.Header.Get("X-Request-Id")
|
||
if requestID == "" {
|
||
requestID = r.Header.Get("X-Request-ID")
|
||
}
|
||
if requestID != "" {
|
||
w.Header().Set("X-Request-Id", requestID)
|
||
}
|
||
next.ServeHTTP(w, r)
|
||
})
|
||
}
|