chore: harden video archive logging

This commit is contained in:
Your Name 2026-05-27 10:52:00 +08:00
parent e5224ff089
commit 303535b22a
2 changed files with 38 additions and 16 deletions

View File

@ -7,6 +7,7 @@ import { db } from "@/lib/db";
import { message } from "@/lib/db/schema";
import { eq } from "drizzle-orm";
import { getDefaultStorageConfig } from "@/lib/db/queries";
import { createLogger } from "@/lib/observability/logger";
import {
toDbS3UploadConfig,
uploadFile,
@ -14,6 +15,8 @@ import {
} from "@/lib/storage/service";
import type { VideoMetadata } from "@/types/ai";
const logger = createLogger("video-archiver");
interface VideoArchiveOptions {
messageId: string;
temporaryUrl: string;
@ -33,13 +36,13 @@ export class VideoArchiver {
const { messageId, temporaryUrl, taskId, metadata } = options;
try {
console.log(`[VideoArchiver] 📹 开始归档视频:${messageId}`);
logger.info("archive started", { messageId, taskId });
// 1. 更新状态为"归档中"
await this.updateVideoStatus(messageId, "archiving");
// 2. 下载视频
console.log(`[VideoArchiver] ⬇️ 下载视频:${temporaryUrl}`);
logger.info("download started", { messageId, temporaryUrl });
const videoBuffer = await this.downloadVideo(temporaryUrl);
if (!videoBuffer) {
@ -50,7 +53,11 @@ export class VideoArchiver {
const filename = this.generateVideoFilename(messageId, taskId);
// 4. 上传到S3(使用项目统一存储服务)
console.log(`[VideoArchiver] ⬆️ 上传视频到S3:${filename}`);
logger.info("upload started", {
messageId,
filename,
bytes: videoBuffer.length,
});
const permanentUrl = await this.uploadVideoToS3(videoBuffer, filename);
// 5. 更新数据库
@ -61,10 +68,14 @@ export class VideoArchiver {
...metadata,
});
console.log(`[VideoArchiver] ✅ 视频归档完成:${permanentUrl}`);
logger.info("archive completed", {
messageId,
permanentUrl,
bytes: videoBuffer.length,
});
return permanentUrl;
} catch (error) {
console.error(`[VideoArchiver] ❌ 归档失败:`, error);
logger.error("archive failed", error, { messageId, taskId });
// 更新状态为"失败"
await this.updateVideoStatus(messageId, "failed");
@ -95,10 +106,12 @@ export class VideoArchiver {
const arrayBuffer = await response.arrayBuffer();
return Buffer.from(arrayBuffer);
} catch (error) {
console.error(
`[VideoArchiver] 下载失败 (尝试 ${i + 1}/${retries}):`,
error
);
logger.warn("download attempt failed", {
attempt: i + 1,
retries,
url,
error,
});
if (i === retries - 1) {
return null;
@ -121,7 +134,9 @@ export class VideoArchiver {
buffer: Buffer,
filename: string
): Promise<string> {
const defaultStorageConfig = await getDefaultStorageConfig().catch(() => undefined);
const defaultStorageConfig = await getDefaultStorageConfig().catch(
() => undefined
);
const defaultS3Config = toDbS3UploadConfig(defaultStorageConfig);
if (defaultS3Config) {
@ -130,16 +145,22 @@ export class VideoArchiver {
buffer as any,
defaultS3Config
);
console.log(
`[VideoArchiver] 视频已上传到默认存储:${uploaded.url}`,
defaultStorageConfig?.name ? `(config=${defaultStorageConfig.name})` : ""
);
logger.info("upload completed with default storage", {
filename,
url: uploaded.url,
storageConfigName: defaultStorageConfig?.name,
});
return uploaded.url;
}
console.warn("[VideoArchiver] 默认存储不可用,回退到通用上传策略");
logger.warn("default storage unavailable, using fallback uploader", {
filename,
});
const fallback = await uploadFile(filename, buffer as any);
console.log(`[VideoArchiver] 视频已上传(回退路径):${fallback.url}`);
logger.info("upload completed with fallback storage", {
filename,
url: fallback.url,
});
return fallback.url;
}

View File

@ -17,6 +17,7 @@ const files = [
"app/(chat)/api/chat/_lib/stream.ts",
"app/(chat)/api/chat/_lib/video-models.ts",
"lib/storage/service.ts",
"lib/storage/video-archiver.ts",
"app/(chat)/api/files/upload/route.ts",
"app/(auth)/login/page.tsx",
"app/api/auth/dingtalk/callback/route.ts",