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)
}