Spaces:
Running
Running
File size: 5,240 Bytes
1de7911 | 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 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | package service
import (
"context"
"fmt"
"log"
"os"
"sync"
)
var (
debugMode bool
debugModeOnce sync.Once
)
// IsDebugMode 检查是否启用调试模式
func IsDebugMode() bool {
debugModeOnce.Do(func() {
debugMode = os.Getenv("DEBUG") == "true" || os.Getenv("DEBUG") == "1"
})
return debugMode
}
// RequestLogger 用于收集请求级日志
type RequestLogger struct {
logs []string
mu sync.Mutex
hasError bool
}
// NewRequestLogger 创建新的请求日志记录器
func NewRequestLogger() *RequestLogger {
return &RequestLogger{
logs: make([]string, 0, 20),
}
}
// Log 记录一条日志
func (l *RequestLogger) Log(format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...)
// 如果全局 DEBUG 开启,直接打印
if IsDebugMode() {
log.Print("[DEBUG] " + msg)
return
}
// 否则缓冲
l.mu.Lock()
l.logs = append(l.logs, "[DEBUG] " + msg)
l.mu.Unlock()
}
// MarkError 标记发生错误
func (l *RequestLogger) MarkError() {
l.mu.Lock()
l.hasError = true
l.mu.Unlock()
}
// Flush 输出缓冲的日志(如果有错误)
func (l *RequestLogger) Flush() {
// 只有在非 Debug 模式且发生错误时才需要 Flush (Debug 模式下已经实时打印了)
if !IsDebugMode() && l.hasError {
l.mu.Lock()
defer l.mu.Unlock()
for _, msg := range l.logs {
log.Print(msg)
}
}
}
type contextKey string
const loggerContextKey contextKey = "request_logger"
// WithLogger 将 logger 注入 context
func WithLogger(ctx context.Context, logger *RequestLogger) context.Context {
return context.WithValue(ctx, loggerContextKey, logger)
}
// GetLogger 从 context 获取 logger
func GetLogger(ctx context.Context) *RequestLogger {
val := ctx.Value(loggerContextKey)
if val != nil {
if logger, ok := val.(*RequestLogger); ok {
return logger
}
}
return nil
}
// 辅助函数:获取 logger 并记录
func logToContext(ctx context.Context, format string, args ...interface{}) {
logger := GetLogger(ctx)
if logger != nil {
logger.Log(format, args...)
} else if IsDebugMode() {
log.Printf("[DEBUG] "+format, args...)
}
}
// DebugLog 调试日志输出
func DebugLog(ctx context.Context, format string, args ...interface{}) {
logToContext(ctx, format, args...)
}
// DebugLogRequest 请求开始日志
func DebugLogRequest(ctx context.Context, provider, endpoint, model string) {
logToContext(ctx, "[%s] >>> 请求开始: endpoint=%s, model=%s", provider, endpoint, model)
}
// DebugLogRetry 重试日志
func DebugLogRetry(ctx context.Context, provider string, attempt int, accountID uint, err error) {
if logger := GetLogger(ctx); logger != nil {
logger.MarkError()
}
logToContext(ctx, "[%s] ↻ 重试 #%d: accountID=%d, error=%v", provider, attempt, accountID, err)
}
// DebugLogAccountSelected 账号选择日志
func DebugLogAccountSelected(ctx context.Context, provider string, accountID uint, email string) {
logToContext(ctx, "[%s] ✓ 选择账号: id=%d, email=%s", provider, accountID, email)
}
// DebugLogRequestSent 请求发送日志
func DebugLogRequestSent(ctx context.Context, provider, url string) {
logToContext(ctx, "[%s] → 发送请求: %s", provider, url)
}
// DebugLogResponseReceived 响应接收日志
func DebugLogResponseReceived(ctx context.Context, provider string, statusCode int) {
logToContext(ctx, "[%s] ← 收到响应: status=%d", provider, statusCode)
}
// DebugLogRequestEnd 请求结束日志
func DebugLogRequestEnd(ctx context.Context, provider string, success bool, err error) {
if !success || err != nil {
if logger := GetLogger(ctx); logger != nil {
logger.MarkError()
}
logToContext(ctx, "[%s] <<< 请求完成: success=false, error=%v", provider, err)
} else {
logToContext(ctx, "[%s] <<< 请求完成: success=true", provider)
}
}
// DebugLogRequestHeaders 请求头日志
func DebugLogRequestHeaders(ctx context.Context, provider string, headers map[string][]string) {
logToContext(ctx, "[%s] 请求头:", provider)
for k, v := range headers {
// 隐藏敏感信息
if k == "Authorization" || k == "x-api-key" {
logToContext(ctx, "[%s] %s: ***", provider, k)
} else {
logToContext(ctx, "[%s] %s: %v", provider, k, v)
}
}
}
// DebugLogResponseHeaders 响应头日志
func DebugLogResponseHeaders(ctx context.Context, provider string, headers map[string][]string) {
logToContext(ctx, "[%s] 响应头:", provider)
for k, v := range headers {
// 隐藏敏感信息
if k == "X-Api-Key" || k == "Authorization" {
logToContext(ctx, "[%s] %s: ***", provider, k)
} else {
logToContext(ctx, "[%s] %s: %v", provider, k, v)
}
}
}
// DebugLogActualModel 实际调用模型日志
func DebugLogActualModel(ctx context.Context, provider, requestModel, actualModel string) {
logToContext(ctx, "[%s] 模型映射: %s → %s", provider, requestModel, actualModel)
}
// DebugLogErrorResponse 错误响应内容日志
func DebugLogErrorResponse(ctx context.Context, provider string, statusCode int, body string) {
if logger := GetLogger(ctx); logger != nil {
logger.MarkError()
}
logToContext(ctx, "[%s] ✗ 错误响应 [%d]: %s", provider, statusCode, body)
}
|