merge: perf/db
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
commit
671874a2c4
22 files changed
+1006
-88
No files matched your search
@@ -80,6 +80,11 @@ const RETENTION_KEYS = [
|
||||
"audit",
|
||||
"capabilityStats",
|
||||
"identityPoolArchive",
|
||||
"engineRun",
|
||||
"outboxEvent",
|
||||
"resolutionAttempt",
|
||||
"identityResolved",
|
||||
"siteSnapshot",
|
||||
] as const;
|
||||
export const STORAGE_RETENTION_CARD: CardSpec = {
|
||||
anchor: "storage-retention",
|
||||
@@ -99,6 +104,11 @@ export const STORAGE_RETENTION_CARD: CardSpec = {
|
||||
"未识别资源归档",
|
||||
"未命中的条目这么久没有新证据就归档,仍可手动指定",
|
||||
),
|
||||
dayField("retentionDays", "engineRun", "后台运行记录", "仍被任务记录引用的跟随任务保留"),
|
||||
dayField("retentionDays", "outboxEvent", "已投递的内部事件"),
|
||||
dayField("retentionDays", "resolutionAttempt", "识别尝试记录", "每个资源至少留最近 3 次"),
|
||||
dayField("retentionDays", "identityResolved", "已识别的待识别条目", "忽略和归档的不删"),
|
||||
dayField("retentionDays", "siteSnapshot", "站点快照", "每个站点最近一次成功的保留"),
|
||||
],
|
||||
fromSettings: (s) =>
|
||||
Object.fromEntries(RETENTION_KEYS.map((k) => [`storage.retentionDays.${k}`, n(s.storage.retentionDays[k])])),
|
||||
|
||||
@@ -38,6 +38,7 @@ export const CLEANUP_LABEL: Record<StorageCleanupTarget, string> = {
|
||||
agent_event: "智能体事件",
|
||||
audit: "审计事件",
|
||||
capability_stats: "能力调用统计",
|
||||
pipeline: "流水数据",
|
||||
identity_pool: "未识别资源归档",
|
||||
analyze: "数据库维护",
|
||||
images: "图片缓存容量",
|
||||
@@ -199,6 +200,72 @@ function CleanupTable({ rows }: { rows: CleanupRow[] }) {
|
||||
}
|
||||
|
||||
/** 运行状态页的「存储」节 */
|
||||
type Statements = SystemStorage["db"]["statements"];
|
||||
type StatementRow = Statements["slowest"][number];
|
||||
|
||||
const fmtMs = (ms: number) =>
|
||||
ms >= 1000 ? `${(ms / 1000).toFixed(1)} 秒` : `${ms < 10 ? ms.toFixed(2) : Math.round(ms)} 毫秒`;
|
||||
|
||||
function StatementTable({ rows }: { rows: StatementRow[] }) {
|
||||
return (
|
||||
<DataTable<StatementRow>
|
||||
rows={rows}
|
||||
rowKey={(r) => r.query}
|
||||
empty={{ title: "还没有统计" }}
|
||||
columns={[
|
||||
{
|
||||
key: "query",
|
||||
header: "语句",
|
||||
cell: (r) => (
|
||||
<span className="line-clamp-2 font-mono text-meta break-all" title={r.query}>
|
||||
{r.query}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "calls",
|
||||
header: "次数",
|
||||
align: "right",
|
||||
cell: (r) => <span className="tabular-nums">{r.calls.toLocaleString("zh-CN")}</span>,
|
||||
},
|
||||
{
|
||||
key: "mean",
|
||||
header: "平均",
|
||||
align: "right",
|
||||
cell: (r) => <span className="whitespace-nowrap tabular-nums">{fmtMs(r.meanMs)}</span>,
|
||||
},
|
||||
{
|
||||
key: "total",
|
||||
header: "合计",
|
||||
align: "right",
|
||||
hideBelow: "sm",
|
||||
cell: (r) => <span className="whitespace-nowrap tabular-nums text-muted-foreground">{fmtMs(r.totalMs)}</span>,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** 数据库语句统计(pg_stat_statements,见 docs/runbook/storage.md「数据库性能」) */
|
||||
function StatementsInfo({ st }: { st: Statements }) {
|
||||
return (
|
||||
<TechInfo title="数据库语句统计" columns={1}>
|
||||
{st.enabled ? (
|
||||
<div className="grid gap-6 xl:grid-cols-2">
|
||||
<Panel title="平均最慢" note={`调用 10 次以上${st.since ? ` · 统计自 ${formatDateTime(st.since)}` : ""}`}>
|
||||
<StatementTable rows={st.slowest} />
|
||||
</Panel>
|
||||
<Panel title="调用最多">
|
||||
<StatementTable rows={st.frequent} />
|
||||
</Panel>
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-caption text-muted-foreground">语句统计未启用:{st.note}</p>
|
||||
)}
|
||||
</TechInfo>
|
||||
);
|
||||
}
|
||||
|
||||
export function StorageSection({ health }: { health: SystemHealth }) {
|
||||
const q = useSystemStorage();
|
||||
const s = q.data;
|
||||
@@ -304,6 +371,17 @@ export function StorageSection({ health }: { health: SystemHealth }) {
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "dead",
|
||||
header: "死元组",
|
||||
align: "right",
|
||||
hideBelow: "md",
|
||||
cell: (t) => (
|
||||
<span className="tabular-nums text-muted-foreground">
|
||||
{t.deadRows === null ? "—" : t.deadRows.toLocaleString("zh-CN")}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Panel>
|
||||
@@ -390,6 +468,8 @@ export function StorageSection({ health }: { health: SystemHealth }) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<StatementsInfo st={s.db.statements} />
|
||||
|
||||
<Panel title="清理任务" note="立即清理会把对应的维护任务排入执行,结果看运行记录">
|
||||
<CleanupTable rows={s.cleanup} />
|
||||
</Panel>
|
||||
|
||||
Reference in new issue
Block a user