From f4d272c7fff7ab9ee8724adaafcb08956b67705d Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 27 May 2026 13:16:37 +0800 Subject: [PATCH] chore: govern product planning api logging --- app/api/enhance/pro/config/route.ts | 5 ++++- app/api/product-planning/analyze-image/route.ts | 5 ++++- app/api/product-planning/analyze-sku/route.ts | 5 ++++- app/api/product-planning/analyze/route.ts | 5 ++++- app/api/product-planning/keyword-insight/route.ts | 5 ++++- app/api/product-planning/taobao/item/route.ts | 5 ++++- app/api/product-planning/taobao/month-sale/route.ts | 5 ++++- app/api/product-planning/taobao/qa/route.ts | 5 ++++- app/api/product-planning/taobao/reviews/route.ts | 5 ++++- scripts/check-log-hygiene.mjs | 9 +++++++++ 10 files changed, 45 insertions(+), 9 deletions(-) diff --git a/app/api/enhance/pro/config/route.ts b/app/api/enhance/pro/config/route.ts index fd2602061..fc2a31d70 100644 --- a/app/api/enhance/pro/config/route.ts +++ b/app/api/enhance/pro/config/route.ts @@ -6,8 +6,11 @@ import { normalizeEnhanceProKreaConfig, sanitizeEnhanceProKreaConfigForClient, } from "@/lib/enhance-pro/config"; +import { createLogger } from "@/lib/observability/logger"; import { normalizeEnhanceProPointsPricingConfig } from "@/lib/points/config"; +const logger = createLogger("enhance-pro-config-api"); + export async function GET() { try { const session = await auth(); @@ -31,7 +34,7 @@ export async function GET() { }, }); } catch (error) { - console.error("[Enhance Pro Config] 获取配置失败:", error); + logger.error("config_fetch_failed", error); return NextResponse.json({ error: "获取图像增强 Pro 配置失败" }, { status: 500 }); } } diff --git a/app/api/product-planning/analyze-image/route.ts b/app/api/product-planning/analyze-image/route.ts index 370708af4..984241be4 100644 --- a/app/api/product-planning/analyze-image/route.ts +++ b/app/api/product-planning/analyze-image/route.ts @@ -2,6 +2,7 @@ import { generateText } from "ai"; import { NextRequest, NextResponse } from "next/server"; import { z } from "zod"; import { inlineVisionImages } from "@/lib/ai/vision-inline"; +import { createLogger } from "@/lib/observability/logger"; import { PRODUCT_PLANNING_ADVANCED_DISABLED, PRODUCT_PLANNING_ADVANCED_DISABLED_MESSAGE, @@ -17,6 +18,8 @@ import type { ProductPlanningAnalyzeResponse } from "@/lib/product-planning/type export const runtime = "nodejs"; export const maxDuration = 120; +const logger = createLogger("product-planning-analyze-image-api"); + const requestSchema = z.object({ itemId: z.string().trim().min(1), imageUrl: z.string().trim().url(), @@ -119,7 +122,7 @@ export async function POST(request: NextRequest) { markdown: text, } satisfies ProductPlanningAnalyzeResponse); } catch (error) { - console.error("[ProductPlanning][AnalyzeImage] request failed:", error); + logger.error("request_failed", error); return jsonError(502, "图片分析失败"); } } diff --git a/app/api/product-planning/analyze-sku/route.ts b/app/api/product-planning/analyze-sku/route.ts index 7ef4fe50d..6b1b6d099 100644 --- a/app/api/product-planning/analyze-sku/route.ts +++ b/app/api/product-planning/analyze-sku/route.ts @@ -1,6 +1,7 @@ import { generateText } from "ai"; import { NextRequest, NextResponse } from "next/server"; import { z } from "zod"; +import { createLogger } from "@/lib/observability/logger"; import { buildProductPlanningSkuAnalyzePrompt } from "@/lib/product-planning/analyze"; import { PRODUCT_PLANNING_ADVANCED_DISABLED, @@ -20,6 +21,8 @@ import type { export const runtime = "nodejs"; export const maxDuration = 120; +const logger = createLogger("product-planning-analyze-sku-api"); + const requestSchema = z.object({ itemId: z.string().trim().min(1), title: z.string().trim().optional(), @@ -86,7 +89,7 @@ export async function POST(request: NextRequest) { markdown: text, } satisfies ProductPlanningAnalyzeResponse); } catch (error) { - console.error("[ProductPlanning][AnalyzeSku] request failed:", error); + logger.error("request_failed", error); return jsonError(502, "SKU 卖点分析失败"); } } diff --git a/app/api/product-planning/analyze/route.ts b/app/api/product-planning/analyze/route.ts index 5380a4d29..8063b2cdd 100644 --- a/app/api/product-planning/analyze/route.ts +++ b/app/api/product-planning/analyze/route.ts @@ -1,6 +1,7 @@ import { generateText } from "ai"; import { NextRequest, NextResponse } from "next/server"; import { z } from "zod"; +import { createLogger } from "@/lib/observability/logger"; import { buildProductPlanningAnalyzePrompt } from "@/lib/product-planning/analyze"; import { resolveProductPlanningTextModel } from "@/lib/product-planning/model-runtime"; import { @@ -16,6 +17,8 @@ import type { export const runtime = "nodejs"; export const maxDuration = 120; +const logger = createLogger("product-planning-analyze-api"); + const requestSchema = z.union([ z.object({ kind: z.literal("review"), @@ -101,7 +104,7 @@ export async function POST(request: NextRequest) { }; return NextResponse.json(payload); } catch (error) { - console.error("[ProductPlanning][Analyze] request failed:", error); + logger.error("request_failed", error); return jsonError(502, "AI 分析失败"); } } diff --git a/app/api/product-planning/keyword-insight/route.ts b/app/api/product-planning/keyword-insight/route.ts index 54fcd1ccb..2015870cc 100644 --- a/app/api/product-planning/keyword-insight/route.ts +++ b/app/api/product-planning/keyword-insight/route.ts @@ -1,4 +1,5 @@ import { NextRequest, NextResponse } from "next/server"; +import { createLogger } from "@/lib/observability/logger"; import { PRODUCT_PLANNING_ADVANCED_DISABLED, PRODUCT_PLANNING_ADVANCED_DISABLED_MESSAGE, @@ -18,6 +19,8 @@ import type { export const runtime = "nodejs"; +const logger = createLogger("product-planning-keyword-insight-api"); + function jsonError(status: number, keyword: string, error: string) { const payload: ProductPlanningKeywordInsightResponse = { success: false, @@ -135,7 +138,7 @@ export async function GET(request: NextRequest) { groups: normalizeGroups(data?.items?.magic), } satisfies ProductPlanningKeywordInsightResponse); } catch (error) { - console.error("[ProductPlanning][KeywordInsight] request failed:", error); + logger.error("request_failed", error); return jsonError(502, keyword, "关键词洞察接口调用失败"); } } diff --git a/app/api/product-planning/taobao/item/route.ts b/app/api/product-planning/taobao/item/route.ts index 9d5a066f3..66100b8c4 100644 --- a/app/api/product-planning/taobao/item/route.ts +++ b/app/api/product-planning/taobao/item/route.ts @@ -1,4 +1,5 @@ import { NextRequest, NextResponse } from "next/server"; +import { createLogger } from "@/lib/observability/logger"; import { PRODUCT_PLANNING_ADVANCED_DISABLED, PRODUCT_PLANNING_ADVANCED_DISABLED_MESSAGE, @@ -14,6 +15,8 @@ import type { ProductPlanningTaobaoItemResponse } from "@/lib/product-planning/t export const runtime = "nodejs"; +const logger = createLogger("product-planning-taobao-item-api"); + function jsonError(status: number, error: string) { const payload: ProductPlanningTaobaoItemResponse = { success: false, @@ -48,7 +51,7 @@ export async function GET(request: NextRequest) { item, } satisfies ProductPlanningTaobaoItemResponse); } catch (error) { - console.error("[ProductPlanning][TaobaoItem] request failed:", error); + logger.error("request_failed", error); return jsonError(502, error instanceof Error ? error.message : "淘宝商品详情接口调用失败"); } } diff --git a/app/api/product-planning/taobao/month-sale/route.ts b/app/api/product-planning/taobao/month-sale/route.ts index 63cc5aa58..5c2fad999 100644 --- a/app/api/product-planning/taobao/month-sale/route.ts +++ b/app/api/product-planning/taobao/month-sale/route.ts @@ -1,4 +1,5 @@ import { NextRequest, NextResponse } from "next/server"; +import { createLogger } from "@/lib/observability/logger"; import { PRODUCT_PLANNING_ADVANCED_DISABLED, PRODUCT_PLANNING_ADVANCED_DISABLED_MESSAGE, @@ -14,6 +15,8 @@ import type { ProductPlanningMonthSaleResponse } from "@/lib/product-planning/ty export const runtime = "nodejs"; +const logger = createLogger("product-planning-month-sale-api"); + function jsonError(status: number, itemId: string, error: string) { const payload: ProductPlanningMonthSaleResponse = { success: false, @@ -57,7 +60,7 @@ export async function GET(request: NextRequest) { raw: null, } satisfies ProductPlanningMonthSaleResponse); } catch (error) { - console.error("[ProductPlanning][MonthSale] request failed:", error); + logger.error("request_failed", error); return jsonError(502, itemId, error instanceof Error ? error.message : "月销量接口调用失败"); } } diff --git a/app/api/product-planning/taobao/qa/route.ts b/app/api/product-planning/taobao/qa/route.ts index 3b352981c..f0250ef2f 100644 --- a/app/api/product-planning/taobao/qa/route.ts +++ b/app/api/product-planning/taobao/qa/route.ts @@ -1,5 +1,6 @@ import { NextRequest, NextResponse } from "next/server"; import { z } from "zod"; +import { createLogger } from "@/lib/observability/logger"; import { getResolvedProductPlanningApiConfig } from "@/lib/product-planning/server-config"; import { isProductPlanningEnabled, @@ -11,6 +12,8 @@ import { normalizeText, truncateText, uniqueBy } from "@/lib/product-planning/ut export const runtime = "nodejs"; +const logger = createLogger("product-planning-taobao-qa-api"); + const requestSchema = z.object({ itemId: z.string().trim().min(1), page: z.number().int().min(1).max(20).default(1), @@ -164,7 +167,7 @@ export async function POST(request: NextRequest) { return NextResponse.json(payload); } catch (error) { - console.error("[ProductPlanning][QA] request failed:", error); + logger.error("request_failed", error); return jsonError(502, "问大家接口调用失败"); } } diff --git a/app/api/product-planning/taobao/reviews/route.ts b/app/api/product-planning/taobao/reviews/route.ts index 83eb949cb..0e4e7ed62 100644 --- a/app/api/product-planning/taobao/reviews/route.ts +++ b/app/api/product-planning/taobao/reviews/route.ts @@ -1,4 +1,5 @@ import { NextRequest, NextResponse } from "next/server"; +import { createLogger } from "@/lib/observability/logger"; import type { ProductPlanningRowsResponse, TaobaoReviewRow } from "@/lib/product-planning/types"; import { getResolvedProductPlanningApiConfig } from "@/lib/product-planning/server-config"; import { @@ -10,6 +11,8 @@ import { ensureHttpsUrl } from "@/lib/product-planning/utils"; export const runtime = "nodejs"; +const logger = createLogger("product-planning-taobao-reviews-api"); + function normalizeMediaUrl(value: unknown) { if (typeof value === "string") { return ensureHttpsUrl(value); @@ -103,7 +106,7 @@ export async function GET(request: NextRequest) { return NextResponse.json(payload); } catch (error) { - console.error("[ProductPlanning][Reviews] request failed:", error); + logger.error("request_failed", error); return jsonError(502, "淘宝评价接口调用失败"); } } diff --git a/scripts/check-log-hygiene.mjs b/scripts/check-log-hygiene.mjs index 694ff537f..650f4a70d 100644 --- a/scripts/check-log-hygiene.mjs +++ b/scripts/check-log-hygiene.mjs @@ -35,6 +35,15 @@ const files = [ "app/api/scene-fusion/route.ts", "app/api/angle-edit/route.ts", "app/api/layer-split/route.ts", + "app/api/enhance/pro/config/route.ts", + "app/api/product-planning/analyze-image/route.ts", + "app/api/product-planning/analyze-sku/route.ts", + "app/api/product-planning/analyze/route.ts", + "app/api/product-planning/keyword-insight/route.ts", + "app/api/product-planning/taobao/item/route.ts", + "app/api/product-planning/taobao/month-sale/route.ts", + "app/api/product-planning/taobao/qa/route.ts", + "app/api/product-planning/taobao/reviews/route.ts", "app/api/pick-object/route.ts", "app/api/canvas/world/upload/route.ts", "app/api/canvas/3d/tasks/route.ts",