Skip to content

Commit d6b3e4d

Browse files
authored
Merge pull request #12 from cuipengfei/feature/gemini-api
Feature/gemini api
2 parents 4a1f46f + 3284346 commit d6b3e4d

20 files changed

Lines changed: 4240 additions & 1 deletion

src/lib/debug-logger.ts

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
import { existsSync, mkdirSync } from "node:fs"
2+
import { writeFile } from "node:fs/promises"
3+
import { join } from "node:path"
4+
5+
import type { GeminiRequest } from "~/routes/generate-content/types"
6+
import type {
7+
ChatCompletionsPayload,
8+
ChatCompletionResponse,
9+
} from "~/services/copilot/create-chat-completions"
10+
11+
interface DebugLogData {
12+
timestamp: string
13+
requestId: string
14+
originalGeminiPayload: GeminiRequest
15+
translatedOpenAIPayload: ChatCompletionsPayload | null
16+
error?: string
17+
processingTime?: number
18+
}
19+
20+
export class DebugLogger {
21+
private static instance: DebugLogger | undefined
22+
private logDir: string
23+
24+
private constructor() {
25+
this.logDir = process.env.DEBUG_LOG_DIR || join(process.cwd(), "debug-logs")
26+
this.ensureLogDir()
27+
}
28+
29+
static getInstance(): DebugLogger {
30+
if (!DebugLogger.instance) {
31+
DebugLogger.instance = new DebugLogger()
32+
}
33+
return DebugLogger.instance
34+
}
35+
36+
private ensureLogDir(): void {
37+
if (!existsSync(this.logDir)) {
38+
mkdirSync(this.logDir, { recursive: true })
39+
}
40+
}
41+
42+
private generateLogFileName(requestId: string): string {
43+
const timestamp = new Date().toISOString().replaceAll(/[:.]/g, "-")
44+
return join(this.logDir, `debug-gemini-${timestamp}-${requestId}.log`)
45+
}
46+
47+
async logRequest(data: {
48+
requestId: string
49+
geminiPayload: GeminiRequest
50+
openAIPayload?: ChatCompletionsPayload | null
51+
error?: string
52+
processingTime?: number
53+
}): Promise<void> {
54+
const logData: DebugLogData = {
55+
timestamp: new Date().toISOString(),
56+
requestId: data.requestId,
57+
originalGeminiPayload: data.geminiPayload,
58+
translatedOpenAIPayload: data.openAIPayload ?? null,
59+
error: data.error,
60+
processingTime: data.processingTime,
61+
}
62+
63+
const logPath = this.generateLogFileName(data.requestId)
64+
65+
try {
66+
await writeFile(logPath, JSON.stringify(logData, null, 2), "utf8")
67+
console.log(`[DEBUG] Logged request data to: ${logPath}`)
68+
} catch (writeError) {
69+
console.error(`[DEBUG] Failed to write log file ${logPath}:`, writeError)
70+
}
71+
}
72+
73+
// For backward compatibility during development
74+
static async logGeminiRequest(
75+
geminiPayload: GeminiRequest,
76+
openAIPayload?: ChatCompletionsPayload,
77+
error?: string,
78+
): Promise<void> {
79+
const logger = DebugLogger.getInstance()
80+
const requestId = Math.random().toString(36).slice(2, 8)
81+
await logger.logRequest({ requestId, geminiPayload, openAIPayload, error })
82+
}
83+
84+
// Log GitHub Copilot API Response
85+
static async logCopilotResponse(
86+
response: ChatCompletionResponse,
87+
context?: string,
88+
): Promise<void> {
89+
const logger = DebugLogger.getInstance()
90+
const requestId = Math.random().toString(36).slice(2, 8)
91+
const timestamp = new Date().toISOString().replaceAll(/[:.]/g, "-")
92+
const logPath = join(
93+
logger.logDir,
94+
`debug-copilot-response-${timestamp}-${requestId}.log`,
95+
)
96+
97+
const logData = {
98+
timestamp: new Date().toISOString(),
99+
context: context || "GitHub Copilot API Response",
100+
response,
101+
}
102+
103+
try {
104+
await writeFile(logPath, JSON.stringify(logData, null, 2), "utf8")
105+
console.log(`[DEBUG] Logged Copilot response to: ${logPath}`)
106+
} catch (writeError) {
107+
console.error(
108+
`[DEBUG] Failed to write Copilot response log file ${logPath}:`,
109+
writeError,
110+
)
111+
}
112+
}
113+
114+
// Log any object for debugging purposes
115+
static async logDebugData(
116+
data: unknown,
117+
context: string,
118+
filePrefix = "debug-data",
119+
): Promise<void> {
120+
const logger = DebugLogger.getInstance()
121+
const requestId = Math.random().toString(36).slice(2, 8)
122+
const timestamp = new Date().toISOString().replaceAll(/[:.]/g, "-")
123+
const logPath = join(
124+
logger.logDir,
125+
`${filePrefix}-${timestamp}-${requestId}.log`,
126+
)
127+
128+
const logData = {
129+
timestamp: new Date().toISOString(),
130+
context,
131+
data,
132+
}
133+
134+
try {
135+
await writeFile(logPath, JSON.stringify(logData, null, 2), "utf8")
136+
console.log(`[DEBUG] Logged ${context} to: ${logPath}`)
137+
} catch (writeError) {
138+
console.error(
139+
`[DEBUG] Failed to write debug log file ${logPath}:`,
140+
writeError,
141+
)
142+
}
143+
}
144+
145+
// Log original and translated response comparison
146+
static async logResponseComparison(
147+
originalResponse: unknown,
148+
translatedResponse: unknown,
149+
options: { context: string; filePrefix?: string } = {
150+
context: "Response Comparison",
151+
},
152+
): Promise<void> {
153+
const { context, filePrefix = "debug-comparison" } = options
154+
const logger = DebugLogger.getInstance()
155+
const requestId = Math.random().toString(36).slice(2, 8)
156+
const timestamp = new Date().toISOString().replaceAll(/[:.]/g, "-")
157+
const logPath = join(
158+
logger.logDir,
159+
`${filePrefix}-${timestamp}-${requestId}.log`,
160+
)
161+
162+
const logData = {
163+
timestamp: new Date().toISOString(),
164+
context,
165+
originalResponse,
166+
translatedResponse,
167+
}
168+
169+
try {
170+
await writeFile(logPath, JSON.stringify(logData, null, 2), "utf8")
171+
console.log(`[DEBUG] Logged ${context} comparison to: ${logPath}`)
172+
} catch (writeError) {
173+
console.error(
174+
`[DEBUG] Failed to write comparison log file ${logPath}:`,
175+
writeError,
176+
)
177+
}
178+
}
179+
}

0 commit comments

Comments
 (0)