feat: 首次推送到Gitea - 完整项目代码 + 安全加固 + 知识库
This commit is contained in:
@@ -26,6 +26,9 @@ async function main() {
|
||||
where: { startedAt: { gte: since } },
|
||||
orderBy: { startedAt: "desc" },
|
||||
});
|
||||
// 兼容历史 status 语义:success == completed,error == failed
|
||||
const isOk = (s) => s === "completed" || s === "success";
|
||||
const isBad = (s) => s === "failed" || s === "error";
|
||||
console.log(`\n--- 最近 7 天日志(${logs.length} 条) ---`);
|
||||
const byKey = new Map();
|
||||
for (const l of logs) {
|
||||
@@ -33,8 +36,8 @@ async function main() {
|
||||
byKey.get(l.taskKey).push(l);
|
||||
}
|
||||
for (const [key, list] of byKey.entries()) {
|
||||
const success = list.filter((l) => l.status === "completed").length;
|
||||
const failed = list.filter((l) => l.status === "failed").length;
|
||||
const success = list.filter((l) => isOk(l.status)).length;
|
||||
const failed = list.filter((l) => isBad(l.status)).length;
|
||||
const last = list[0];
|
||||
const lastDate = new Date(last.startedAt).toLocaleString("zh-CN");
|
||||
console.log(` ${key.padEnd(30)} 共${list.length}次 成功${success} 失败${failed} 最近=${lastDate} status=${last.status}`);
|
||||
@@ -45,6 +48,7 @@ async function main() {
|
||||
const executedKeys = new Set(logs.map((l) => l.taskKey));
|
||||
const allExpectedKeys = new Set([
|
||||
...configs.map((c) => c.taskKey),
|
||||
// 工具/技能发现
|
||||
"task1-discover-tools",
|
||||
"task3-check-tools",
|
||||
"task4-discover-skills",
|
||||
@@ -52,11 +56,34 @@ async function main() {
|
||||
"task6-review-hot",
|
||||
"task7-news-to-community",
|
||||
"daily-news",
|
||||
// Bot 核心引擎
|
||||
"bot-activity",
|
||||
"bot-affinity-update",
|
||||
"bot-feedback-loop",
|
||||
"bot-weekly-review",
|
||||
"bot-skill-crystallize",
|
||||
"bot-affinity-update",
|
||||
"bot-weekly-review",
|
||||
"bot-feedback-loop",
|
||||
"bot-adversarial-learning-run",
|
||||
"bot-persona-experiment-run",
|
||||
"bot-roundtable",
|
||||
// 运维
|
||||
"cleanup-logs",
|
||||
"cleanup-task-logs",
|
||||
"reconcile-like-counts",
|
||||
"health-check",
|
||||
// 内容运营
|
||||
"weekly-recommend-email",
|
||||
"grant-freeze-cards",
|
||||
"notification-digest",
|
||||
"newsletter-generate",
|
||||
// 竞品/趋势
|
||||
"competitor-monitor",
|
||||
"trend-alert",
|
||||
// 数据维护
|
||||
"enrich-tool-data",
|
||||
// 行业智库
|
||||
"industry-thinktank",
|
||||
// 行业情报日更
|
||||
"industry-daily",
|
||||
]);
|
||||
const knownButNeverRun = [...allExpectedKeys].filter((k) => !executedKeys.has(k));
|
||||
console.log("从未执行:", knownButNeverRun.length ? knownButNeverRun.join(", ") : "无");
|
||||
@@ -73,6 +100,13 @@ async function main() {
|
||||
orderBy: { createdAt: "desc" },
|
||||
select: { createdAt: true, title: true },
|
||||
});
|
||||
// 新形态(每日情报):Bot 主要产出是"楼层/帖子",主题帖只创建一次,
|
||||
// 因此活跃度判定必须用最新的 Bot 楼层(post)而不是主题帖创建时间
|
||||
const lastBotPost = await prisma.forumPost.findFirst({
|
||||
where: { user: { isBot: true } },
|
||||
orderBy: { createdAt: "desc" },
|
||||
select: { createdAt: true, content: true },
|
||||
});
|
||||
console.log(` Bot 用户总数: ${totalBots}`);
|
||||
console.log(` BotConfig 数: ${totalBotConfigs}`);
|
||||
console.log(` BotMemory 数: ${totalMemories}`);
|
||||
@@ -86,13 +120,45 @@ async function main() {
|
||||
}
|
||||
|
||||
// 5. 最近失败的详情
|
||||
const recentFailed = logs.filter((l) => l.status === "failed").slice(0, 5);
|
||||
const recentFailed = logs.filter((l) => isBad(l.status)).slice(0, 5);
|
||||
console.log(`\n--- 最近失败任务 (${recentFailed.length}) ---`);
|
||||
for (const f of recentFailed) {
|
||||
console.log(` ${f.taskKey} @ ${new Date(f.startedAt).toLocaleString("zh-CN")}`);
|
||||
if (f.error) console.log(` ${f.error.substring(0, 200)}`);
|
||||
}
|
||||
|
||||
// 6. 告警汇总
|
||||
const criticalFailures = logs.filter(l => isBad(l.status) && (Date.now() - new Date(l.startedAt).getTime()) < 24 * 3600 * 1000);
|
||||
console.log("\n--- ⚠️ 24小时告警汇总 ---");
|
||||
if (criticalFailures.length === 0) {
|
||||
console.log(" ✅ 无告警,所有任务正常");
|
||||
} else {
|
||||
console.log(` 🚨 ${criticalFailures.length} 个任务失败!`);
|
||||
for (const f of criticalFailures) {
|
||||
console.log(` - ${f.taskKey}: ${f.error?.substring(0, 100) || '未知错误'}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Bot 活跃度(新形态):以"行业情报日更引擎最近一次执行"为准(发布/跳过都算在跑),
|
||||
// 引擎每天 08:30(北京)一次,故阈值 26h;无执行记录时回退到最新 Bot 楼层时间
|
||||
const lastDailyRun = await prisma.taskLog.findFirst({
|
||||
where: { taskKey: "industry-daily" },
|
||||
orderBy: { startedAt: "desc" },
|
||||
select: { startedAt: true, status: true, result: true },
|
||||
});
|
||||
const lastActiveAt = lastDailyRun ? new Date(lastDailyRun.startedAt) : lastBotPost ? new Date(lastBotPost.createdAt) : null;
|
||||
if (lastActiveAt) {
|
||||
const hoursAgo = (Date.now() - lastActiveAt.getTime()) / 3600000;
|
||||
const which = lastDailyRun ? `日更引擎(${lastDailyRun.status})` : "Bot 楼层";
|
||||
if (hoursAgo > 26) {
|
||||
console.log(` 🚨 Bot 体系活跃异常:最近 ${which} 在 ${hoursAgo.toFixed(1)}h 前(>26h),请检查 industry-daily 调度!`);
|
||||
} else {
|
||||
console.log(` ✅ Bot 活动正常(最近 ${which} ${hoursAgo.toFixed(1)}h 前)`);
|
||||
}
|
||||
} else {
|
||||
console.log(" ⚠️ 无 Bot 活跃记录(industry-daily 尚未执行过)");
|
||||
}
|
||||
|
||||
await prisma.$disconnect();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user