chore: govern layer split logging
This commit is contained in:
parent
8e91c00c74
commit
37ed4b83b2
@ -1,6 +1,9 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { auth } from "@/app/(auth)/auth";
|
||||
import { executeLayerSplitJob, LayerSplitServiceError } from "@/lib/ai/layer-split/service";
|
||||
import { createLogger } from "@/lib/observability/logger";
|
||||
|
||||
const logger = createLogger("layer-split-api");
|
||||
|
||||
export const runtime = "nodejs";
|
||||
export const maxDuration = 300;
|
||||
@ -51,7 +54,7 @@ export async function POST(request: NextRequest) {
|
||||
);
|
||||
}
|
||||
|
||||
console.error("[LayerSplit API] 处理错误:", error);
|
||||
logger.error("request_failed", error);
|
||||
return NextResponse.json(
|
||||
{ error: "服务器内部错误", detail: error instanceof Error ? error.message : "未知错误" },
|
||||
{ status: 500 }
|
||||
|
||||
@ -1,12 +1,20 @@
|
||||
import "server-only";
|
||||
|
||||
import JSZip from "jszip";
|
||||
import { createMediaAssetRelation, getMediaAssetsByUserAndUrls, getSystemSetting, upsertMediaAsset } from "@/lib/db/queries";
|
||||
import {
|
||||
createMediaAssetRelation,
|
||||
getMediaAssetsByUserAndUrls,
|
||||
getSystemSetting,
|
||||
upsertMediaAsset,
|
||||
} from "@/lib/db/queries";
|
||||
import { db } from "@/lib/db";
|
||||
import { generatedImage } from "@/lib/db/schema";
|
||||
import { createLogger } from "@/lib/observability/logger";
|
||||
import { ensurePublicImageUrl } from "@/lib/realtime/image-input";
|
||||
import { uploadFile } from "@/lib/storage/service";
|
||||
|
||||
const logger = createLogger("layer-split-service");
|
||||
|
||||
const LAYER_SPLIT_CONFIG_KEY = "layer_split_config";
|
||||
const DEFAULT_REPLICATE_BASE_URL = "https://api.replicate.com/v1";
|
||||
const DEFAULT_LAYER_SPLIT_MODEL = "qwen/qwen-image-layered";
|
||||
@ -443,7 +451,7 @@ async function createThumbnail(buffer: Buffer, mimeType: string): Promise<Buffer
|
||||
}
|
||||
return await pipeline.png({ compressionLevel: 8 }).toBuffer();
|
||||
} catch (error) {
|
||||
console.error("[LayerSplit] Failed to create thumbnail:", error);
|
||||
logger.warn("thumbnail_creation_failed", error);
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
@ -497,7 +505,7 @@ async function detectVisibleBounds(buffer: Buffer) {
|
||||
coverage: visiblePixels / (width * height),
|
||||
};
|
||||
} catch (error) {
|
||||
console.warn("[LayerSplit] Failed to detect visible bounds:", error);
|
||||
logger.warn("visible_bounds_detection_failed", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -524,6 +532,15 @@ async function uploadBufferPair(buffer: Buffer, mimeType: string, prefix: string
|
||||
uploadFile(origFilename, originalArrayBuffer),
|
||||
]);
|
||||
|
||||
logger.info("layer_upload_completed", {
|
||||
mimeType,
|
||||
originalBytes: buffer.length,
|
||||
originalUrl: originalResult.url,
|
||||
prefix,
|
||||
thumbnailBytes: thumbnailBuffer.length,
|
||||
thumbnailUrl: thumbnailResult.url,
|
||||
});
|
||||
|
||||
return {
|
||||
thumbnail: thumbnailResult.url,
|
||||
original: originalResult.url,
|
||||
@ -573,6 +590,11 @@ async function runReplicateLayerSplit(params: {
|
||||
});
|
||||
|
||||
lastPayload = payload;
|
||||
logger.debug("replicate_prediction_attempt_completed", {
|
||||
attempt: index + 1,
|
||||
hasPayload: payload != null,
|
||||
status: response.status,
|
||||
});
|
||||
|
||||
if (
|
||||
response.ok &&
|
||||
@ -601,6 +623,10 @@ async function runReplicateLayerSplit(params: {
|
||||
}
|
||||
|
||||
if (index < candidateInputs.length - 1 && shouldRetryWithAlternativeInput(errorMessage)) {
|
||||
logger.warn("replicate_retrying_with_alternative_input", {
|
||||
attempt: index + 1,
|
||||
reasonLength: errorMessage.length,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -615,6 +641,13 @@ async function runReplicateLayerSplit(params: {
|
||||
export async function executeLayerSplitJob(params: LayerSplitParams): Promise<ExecuteLayerSplitJobResult> {
|
||||
const startedAt = Date.now();
|
||||
const config = await getValidatedLayerSplitConfig();
|
||||
logger.info("job_started", {
|
||||
hasChatId: Boolean(params.chatId),
|
||||
hasMessageId: Boolean(params.messageId),
|
||||
hasPrompt: Boolean(params.prompt),
|
||||
hasSourceNodeId: Boolean(params.sourceNodeId),
|
||||
skipGallerySave: Boolean(params.skipGallerySave),
|
||||
});
|
||||
const normalizedImageUrl = await ensurePublicImageUrl({
|
||||
imageUrl: params.imageUrl,
|
||||
prefix: "layer-split-input",
|
||||
@ -630,6 +663,10 @@ export async function executeLayerSplitJob(params: LayerSplitParams): Promise<Ex
|
||||
|
||||
const layerBuffers = await resolveLayerArtifacts(payload);
|
||||
const totalLayers = layerBuffers.length;
|
||||
logger.info("layer_artifacts_resolved", {
|
||||
model: config.replicateModel,
|
||||
totalLayers,
|
||||
});
|
||||
const sourceAssets = await getMediaAssetsByUserAndUrls({
|
||||
userId: params.userId,
|
||||
urls:
|
||||
@ -724,10 +761,17 @@ export async function executeLayerSplitJob(params: LayerSplitParams): Promise<Ex
|
||||
});
|
||||
}
|
||||
|
||||
const processingTime = (Date.now() - startedAt) / 1000;
|
||||
logger.info("job_completed", {
|
||||
layerCount: results.length,
|
||||
processingSeconds: Number(processingTime.toFixed(2)),
|
||||
savedToGallery: !params.skipGallerySave,
|
||||
});
|
||||
|
||||
return {
|
||||
layers: results,
|
||||
provider: "replicate",
|
||||
model: config.replicateModel,
|
||||
processingTime: (Date.now() - startedAt) / 1000,
|
||||
processingTime,
|
||||
};
|
||||
}
|
||||
|
||||
@ -25,6 +25,7 @@ const files = [
|
||||
"lib/ai/providers/volcano-vision.ts",
|
||||
"lib/ai/providers/qianwen-video.ts",
|
||||
"lib/ai/rmbg/service.ts",
|
||||
"lib/ai/layer-split/service.ts",
|
||||
"lib/ai/dynamic-provider.ts",
|
||||
"services/canvas/index.ts",
|
||||
"components/image-annotator.tsx",
|
||||
@ -33,6 +34,7 @@ const files = [
|
||||
"app/api/canvas/detail-plan/route.ts",
|
||||
"app/api/scene-fusion/route.ts",
|
||||
"app/api/angle-edit/route.ts",
|
||||
"app/api/layer-split/route.ts",
|
||||
"app/api/pick-object/route.ts",
|
||||
"app/api/canvas/world/upload/route.ts",
|
||||
"app/api/canvas/3d/tasks/route.ts",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user