diff --git a/app/api/canvas/3d/tasks/[taskId]/route.ts b/app/api/canvas/3d/tasks/[taskId]/route.ts index 24efce538..cb9af5f55 100644 --- a/app/api/canvas/3d/tasks/[taskId]/route.ts +++ b/app/api/canvas/3d/tasks/[taskId]/route.ts @@ -4,6 +4,8 @@ import { auth } from "@/app/(auth)/auth"; import { db } from "@/lib/db"; import { refundUserPoints } from "@/lib/db/queries"; import { pointsLedger } from "@/lib/db/schema"; +import { createLogger } from "@/lib/observability/logger"; +import { uploadFile } from "@/lib/storage/service"; import { TripoApiError, pickTaskModelUrl, @@ -15,11 +17,12 @@ import { resolveTripoProviderConfigForTaskId, } from "@/lib/tripo/server"; import type { TripoTaskData } from "@/lib/tripo/types"; -import { uploadFile } from "@/lib/storage/service"; export const runtime = "nodejs"; export const maxDuration = 120; +const logger = createLogger("canvas-3d-task-status"); + type RemoteAssetArchiveCacheItem = { sourceUrl: string; archivedUrl: string; @@ -171,7 +174,7 @@ async function archiveTripoModelIfNeeded(params: { archivedUrl: uploaded.url, }); - console.log("[TripoAssetArchive] success", { + logger.info("asset archive completed", { taskId: params.taskId, cacheKey: params.cacheKey, sourceHost: new URL(sourceUrl).hostname, @@ -181,11 +184,11 @@ async function archiveTripoModelIfNeeded(params: { return uploaded.url; } catch (error) { - console.error("[TripoAssetArchive] failed", { + logger.warn("asset archive failed", { taskId: params.taskId, cacheKey: params.cacheKey, sourceUrl, - error: error instanceof Error ? error.message : String(error), + error, }); return null; } finally { @@ -287,7 +290,7 @@ async function refundModel3DPointsForFailedTask(params: { }); if (!refundResult.ok) { - console.error("[Points] Failed to refund failed 3D model task:", { + logger.error("points refund failed", { taskId: params.taskId, userId: params.userId, errorMessage: params.errorMessage, @@ -329,12 +332,15 @@ export async function GET(request: Request, { params }: RouteParams) { const taskStatus = String(result.data.status || ""); const errorMessage = String(result.data.error_msg || "").trim(); const refundedPoints = isFailedTripoStatus(taskStatus) - ? await refundModel3DPointsForFailedTask({ + ? await refundModel3DPointsForFailedTask({ userId: session.user.id, taskId: normalizedTaskId, errorMessage, }).catch((refundError) => { - console.error("[Points] Failed to handle 3D task refund:", refundError); + logger.error("points refund handler failed", refundError, { + taskId: normalizedTaskId, + userId: session.user.id, + }); return 0; }) : 0; @@ -407,16 +413,17 @@ export async function GET(request: Request, { params }: RouteParams) { if (error instanceof TripoApiError) { const shouldRefundMissingTask = error.code === 2001 || /task\s+is\s+not\s+found/i.test(error.message); + const missingTaskRefundContext = refundContext; const refundedPoints = - shouldRefundMissingTask && refundContext + shouldRefundMissingTask && missingTaskRefundContext ? await refundModel3DPointsForFailedTask({ - ...refundContext, + ...missingTaskRefundContext, errorMessage: error.message, }).catch((refundError) => { - console.error( - "[Points] Failed to refund missing 3D task:", - refundError - ); + logger.error("missing task refund failed", refundError, { + taskId: missingTaskRefundContext.taskId, + userId: missingTaskRefundContext.userId, + }); return 0; }) : 0; diff --git a/scripts/check-log-hygiene.mjs b/scripts/check-log-hygiene.mjs index 2b20ebbcc..f306be16b 100644 --- a/scripts/check-log-hygiene.mjs +++ b/scripts/check-log-hygiene.mjs @@ -34,6 +34,7 @@ const files = [ "app/api/pick-object/route.ts", "app/api/canvas/world/upload/route.ts", "app/api/canvas/3d/tasks/route.ts", + "app/api/canvas/3d/tasks/[taskId]/route.ts", ]; const consolePattern = /\bconsole\.(log|warn|error|info|debug)\b/g;