feat(ai): reichhaltigeres Logging fuer AI_FAILED-Diagnose
All checks were successful
Build & Publish Docker Image / build-and-push (push) Successful in 2m15s
All checks were successful
Build & Publish Docker Image / build-and-push (push) Successful in 2m15s
Der bisherige Log "[extract-from-photo] AI_FAILED after 43165ms, 385807 bytes" verriet nicht, ob es JSON-Parse, Schema-Validierung oder ein SDK-Fehler war. Endpoint haengt jetzt e.message an; gemini-client loggt den First-Attempt-Fehler vor dem Retry und packt bei AI_FAILED beide Messages in den finalen Error. Keine Prompt-/Response-Inhalte werden geloggt -- nur unsere eigenen GeminiError-Messages (Zod-Pfade, "non-JSON output", SDK-toString). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -114,6 +114,7 @@ export async function extractRecipeFromImage(
|
|||||||
imageBuffer: Buffer,
|
imageBuffer: Buffer,
|
||||||
mimeType: string
|
mimeType: string
|
||||||
): Promise<ExtractionResponse> {
|
): Promise<ExtractionResponse> {
|
||||||
|
let firstMsg: string | null = null;
|
||||||
try {
|
try {
|
||||||
return await callGemini(imageBuffer, mimeType);
|
return await callGemini(imageBuffer, mimeType);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -132,6 +133,9 @@ export async function extractRecipeFromImage(
|
|||||||
: new GeminiError('AI_FAILED', String(e));
|
: new GeminiError('AI_FAILED', String(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
firstMsg = e instanceof Error ? e.message : String(e);
|
||||||
|
console.warn(`[gemini-client] first attempt failed, retrying: ${firstMsg}`);
|
||||||
|
|
||||||
await new Promise((r) => setTimeout(r, 500));
|
await new Promise((r) => setTimeout(r, 500));
|
||||||
try {
|
try {
|
||||||
return await callGemini(
|
return await callGemini(
|
||||||
@@ -140,11 +144,23 @@ export async function extractRecipeFromImage(
|
|||||||
'Dein vorheriger Output war ungültig. Bitte antworte ausschließlich mit JSON gemäß Schema.'
|
'Dein vorheriger Output war ungültig. Bitte antworte ausschließlich mit JSON gemäß Schema.'
|
||||||
);
|
);
|
||||||
} catch (retryErr) {
|
} catch (retryErr) {
|
||||||
if (retryErr instanceof GeminiError) throw retryErr;
|
const retryMsg = retryErr instanceof Error ? retryErr.message : String(retryErr);
|
||||||
|
if (retryErr instanceof GeminiError) {
|
||||||
|
if (retryErr.code === 'AI_FAILED') {
|
||||||
|
throw new GeminiError(
|
||||||
|
'AI_FAILED',
|
||||||
|
`retry failed: ${retryMsg} (first: ${firstMsg})`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
throw retryErr;
|
||||||
|
}
|
||||||
const retryStatus = getStatus(retryErr);
|
const retryStatus = getStatus(retryErr);
|
||||||
if (retryStatus === 429)
|
if (retryStatus === 429)
|
||||||
throw new GeminiError('AI_RATE_LIMITED', 'Gemini rate limit on retry');
|
throw new GeminiError('AI_RATE_LIMITED', 'Gemini rate limit on retry');
|
||||||
throw new GeminiError('AI_FAILED', String(retryErr));
|
throw new GeminiError(
|
||||||
|
'AI_FAILED',
|
||||||
|
`retry failed: ${retryMsg} (first: ${firstMsg})`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,9 +121,11 @@ export const POST: RequestHandler = async ({ request, getClientAddress }) => {
|
|||||||
: e.code === 'AI_NOT_CONFIGURED'
|
: e.code === 'AI_NOT_CONFIGURED'
|
||||||
? 503
|
? 503
|
||||||
: 503;
|
: 503;
|
||||||
// Nur Code + Meta loggen, niemals Prompt/Response-Inhalt.
|
// Nur Code + Meta + Error-Message loggen, niemals Prompt/Response-Inhalt.
|
||||||
|
// e.message enthaelt z.B. Zod-Validierungspfade oder "non-JSON output" --
|
||||||
|
// kein AI-Content, aber die Diagnose-Info, warum AI_FAILED kam.
|
||||||
console.warn(
|
console.warn(
|
||||||
`[extract-from-photo] ${e.code} after ${Date.now() - startedAt}ms, ${preprocessed.buffer.byteLength} bytes`
|
`[extract-from-photo] ${e.code} after ${Date.now() - startedAt}ms, ${preprocessed.buffer.byteLength} bytes: ${e.message}`
|
||||||
);
|
);
|
||||||
return errJson(status, e.code, 'Die Bild-Analyse ist fehlgeschlagen.');
|
return errJson(status, e.code, 'Die Bild-Analyse ist fehlgeschlagen.');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user