From 8e91c00c74dd158c8f687b0d9546aa0cb4831ac2 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 27 May 2026 13:06:01 +0800 Subject: [PATCH] chore: govern rmbg service logging --- lib/ai/rmbg/service.ts | 107 +++++++++++++++++++++++++++++----- scripts/check-log-hygiene.mjs | 1 + 2 files changed, 95 insertions(+), 13 deletions(-) diff --git a/lib/ai/rmbg/service.ts b/lib/ai/rmbg/service.ts index 4babf76ef..97438fe0b 100644 --- a/lib/ai/rmbg/service.ts +++ b/lib/ai/rmbg/service.ts @@ -6,8 +6,11 @@ import { } from "@/lib/db/queries"; import { db } from "@/lib/db"; import { generatedImage } from "@/lib/db/schema"; +import { createLogger } from "@/lib/observability/logger"; import { uploadFile } from "@/lib/storage/service"; +const logger = createLogger("rmbg-service"); + export type RmbgProvider = "rmbg" | "photoroom" | "aoscdn"; type RmbgConfig = { @@ -73,7 +76,7 @@ async function createThumbnail(buffer: Buffer, mimeType: string): Promise null); if (!createResponse.ok || !createPayload?.data?.task_id) { + logger.warn("aos_task_create_failed", { + hasPayload: createPayload != null, + status: createResponse.status, + }); return { success: false, error: `AOS任务创建失败: ${createPayload?.message || createResponse.statusText}`, @@ -368,6 +392,10 @@ async function processWithAosSegmentation( const pollPayload = await pollResponse.json().catch(() => null); if (!pollResponse.ok || !pollPayload?.data) { + logger.warn("aos_task_poll_failed", { + hasPayload: pollPayload != null, + status: pollResponse.status, + }); return { success: false, error: `AOS任务查询失败: ${pollPayload?.message || pollResponse.statusText}`, @@ -380,6 +408,10 @@ async function processWithAosSegmentation( const errMessage = String(pollPayload.data.err_message || pollPayload.data.err_info || ""); if (state === 1 && imageUrl) { + logger.debug("aos_task_completed", { + pollCount, + taskId, + }); const imageResponse = await withTimeout( (signal) => fetch(imageUrl, { @@ -390,6 +422,10 @@ async function processWithAosSegmentation( ); if (!imageResponse.ok) { + logger.warn("aos_result_download_failed", { + status: imageResponse.status, + taskId, + }); return { success: false, error: `AOS结果下载失败: ${imageResponse.status} ${imageResponse.statusText}`, @@ -405,6 +441,11 @@ async function processWithAosSegmentation( } if (state < 0) { + logger.warn("aos_task_failed", { + hasErrorMessage: Boolean(errMessage), + state, + taskId, + }); return { success: false, error: `AOS任务失败: ${errMessage || stateDetail || pollPayload?.message || "状态异常"}`, @@ -412,11 +453,13 @@ async function processWithAosSegmentation( } } + logger.warn("aos_task_timeout", { maxPollCount }); return { success: false, error: "AOS任务超时(最多60秒)" }; } catch (error) { if (error instanceof Error && error.name === "AbortError") { return { success: false, error: "AOS请求超时,请稍后重试" }; } + logger.warn("aos_provider_request_error", error); return { success: false, error: error instanceof Error ? error.message : "未知错误" }; } } @@ -468,7 +511,7 @@ export async function fetchImageBufferFromUrl(imageUrl: string): Promise if (error instanceof RmbgServiceError) { throw error; } - console.error("[RMBG] 获取图片失败:", error); + logger.warn("source_image_fetch_failed", error); throw new RmbgServiceError("无法获取图片,请检查图片链接是否有效", 400); } } @@ -488,7 +531,14 @@ export async function executeRmbgJob( } = params; const { provider, config } = await getValidatedRmbgConfig(); - console.log(`[RMBG] Using provider: ${provider}`); + logger.info("job_started", { + hasChatId: Boolean(chatId), + hasMessageId: Boolean(messageId), + hasSourceImageUrl: Boolean(sourceImageUrl), + inputBytes: imageBuffer.length, + provider, + skipGallerySave, + }); let resultBuffer: Buffer; let resultBase64: string; @@ -497,6 +547,10 @@ export async function executeRmbgJob( if (provider === "photoroom") { const result = await processWithPhotoRoom(imageBuffer, config.photoroomApiKey!); if (!result.success || !result.imageBuffer) { + logger.warn("job_provider_failed", { + provider, + reasonLength: result.error?.length ?? 0, + }); throw new RmbgServiceError("抠图处理失败", 500, result.error); } resultBuffer = result.imageBuffer; @@ -514,7 +568,16 @@ export async function executeRmbgJob( if (!result.success || !result.imageBuffer) { const detail = result.error || "AOS处理失败"; const friendlyMessage = getAosFriendlyErrorMessage(detail); - throw new RmbgServiceError("抠图处理失败", friendlyMessage ? 400 : 500, friendlyMessage || detail); + logger.warn("job_provider_failed", { + friendly: Boolean(friendlyMessage), + provider, + reasonLength: detail.length, + }); + throw new RmbgServiceError( + "抠图处理失败", + friendlyMessage ? 400 : 500, + friendlyMessage || detail + ); } resultBuffer = result.imageBuffer; @@ -527,6 +590,10 @@ export async function executeRmbgJob( }); if (!result.success || !result.image_base64) { + logger.warn("job_provider_failed", { + provider, + reasonLength: result.error?.length ?? 0, + }); throw new RmbgServiceError("抠图处理失败", 500, result.error); } @@ -575,7 +642,7 @@ export async function executeRmbgJob( } if (!saved) { - console.error("[RMBG] ❌ 保存到数据库失败:", saveError); + logger.error("gallery_save_failed", saveError); throw new RmbgServiceError("图片处理成功但保存到相册失败,请稍后重试", 500); } @@ -628,9 +695,17 @@ export async function executeRmbgJob( } } } catch (assetError) { - console.error("[RMBG] ⚠️ MediaAsset 注册失败:", assetError); + logger.warn("media_asset_registration_failed", assetError); } + logger.info("job_completed", { + generatedImageId: savedImage.id, + mediaAssetId, + processingSeconds: Number(processingTime.toFixed(2)), + provider, + savedToGallery: true, + }); + return { image_base64: resultBase64, thumbnail_url: thumbnailUrl, @@ -642,9 +717,15 @@ export async function executeRmbgJob( }; } } else { - console.log("[RMBG] Skip gallery save by request flag"); + logger.info("gallery_save_skipped", { provider }); } + logger.info("job_completed", { + processingSeconds: Number(processingTime.toFixed(2)), + provider, + savedToGallery: false, + }); + return { image_base64: resultBase64, thumbnail_url: thumbnailUrl, diff --git a/scripts/check-log-hygiene.mjs b/scripts/check-log-hygiene.mjs index a0cd87fd6..9df922475 100644 --- a/scripts/check-log-hygiene.mjs +++ b/scripts/check-log-hygiene.mjs @@ -24,6 +24,7 @@ const files = [ "lib/ai/providers/gemini-image.ts", "lib/ai/providers/volcano-vision.ts", "lib/ai/providers/qianwen-video.ts", + "lib/ai/rmbg/service.ts", "lib/ai/dynamic-provider.ts", "services/canvas/index.ts", "components/image-annotator.tsx",