mirror of
https://github.com/hansjone/netx.git
synced 2026-10-09 03:10:46 +08:00
Show collect start/end times on biz-state task and batch lists.
Helps tune schedule interval from last-run window and batch duration. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
12b60c2a52
commit
c15ea00a23
4 changed files with 48 additions and 4 deletions
|
|
@ -428,6 +428,9 @@ def list_tasks(db: Session, *, purpose: str | None = None) -> list[dict[str, Any
|
||||||
"interval_sec": t.interval_sec,
|
"interval_sec": t.interval_sec,
|
||||||
"collect_running": bool(t.collect_running),
|
"collect_running": bool(t.collect_running),
|
||||||
"last_error": t.last_error,
|
"last_error": t.last_error,
|
||||||
|
"last_collect_started_at": t.last_collect_started_at.isoformat() + "Z"
|
||||||
|
if t.last_collect_started_at
|
||||||
|
else None,
|
||||||
"last_collect_ended_at": t.last_collect_ended_at.isoformat() + "Z"
|
"last_collect_ended_at": t.last_collect_ended_at.isoformat() + "Z"
|
||||||
if t.last_collect_ended_at
|
if t.last_collect_ended_at
|
||||||
else None,
|
else None,
|
||||||
|
|
|
||||||
|
|
@ -295,6 +295,8 @@ const en = {
|
||||||
colNe: "NE",
|
colNe: "NE",
|
||||||
colStatus: "Status",
|
colStatus: "Status",
|
||||||
colLast: "Last collect",
|
colLast: "Last collect",
|
||||||
|
colStarted: "Started",
|
||||||
|
colEnded: "Ended",
|
||||||
colTime: "Time",
|
colTime: "Time",
|
||||||
colRows: "Rows",
|
colRows: "Rows",
|
||||||
colActions: "Actions",
|
colActions: "Actions",
|
||||||
|
|
|
||||||
|
|
@ -295,6 +295,8 @@ const zh = {
|
||||||
colNe: "网元",
|
colNe: "网元",
|
||||||
colStatus: "状态",
|
colStatus: "状态",
|
||||||
colLast: "最近采集",
|
colLast: "最近采集",
|
||||||
|
colStarted: "开始时间",
|
||||||
|
colEnded: "结束时间",
|
||||||
colTime: "时间",
|
colTime: "时间",
|
||||||
colRows: "行数",
|
colRows: "行数",
|
||||||
colActions: "操作",
|
colActions: "操作",
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ type TaskRow = {
|
||||||
status: string;
|
status: string;
|
||||||
collect_running: boolean;
|
collect_running: boolean;
|
||||||
last_error: string;
|
last_error: string;
|
||||||
|
last_collect_started_at?: string | null;
|
||||||
last_collect_ended_at?: string | null;
|
last_collect_ended_at?: string | null;
|
||||||
interval_sec?: number;
|
interval_sec?: number;
|
||||||
};
|
};
|
||||||
|
|
@ -82,6 +83,7 @@ type BatchRow = {
|
||||||
row_count: number;
|
row_count: number;
|
||||||
command_count: number;
|
command_count: number;
|
||||||
started_at?: string | null;
|
started_at?: string | null;
|
||||||
|
ended_at?: string | null;
|
||||||
is_baseline?: boolean;
|
is_baseline?: boolean;
|
||||||
protected?: boolean;
|
protected?: boolean;
|
||||||
protect_reasons?: string[];
|
protect_reasons?: string[];
|
||||||
|
|
@ -169,6 +171,21 @@ function fmtTime(v?: string | null) {
|
||||||
return formatSystemTime(v) || v;
|
return formatSystemTime(v) || v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fmtDuration(started?: string | null, ended?: string | null) {
|
||||||
|
if (!started || !ended) return "";
|
||||||
|
const a = Date.parse(started);
|
||||||
|
const b = Date.parse(ended);
|
||||||
|
if (!Number.isFinite(a) || !Number.isFinite(b) || b < a) return "";
|
||||||
|
const sec = Math.round((b - a) / 1000);
|
||||||
|
if (sec < 60) return `${sec}s`;
|
||||||
|
const m = Math.floor(sec / 60);
|
||||||
|
const s = sec % 60;
|
||||||
|
if (m < 60) return s ? `${m}m${s}s` : `${m}m`;
|
||||||
|
const h = Math.floor(m / 60);
|
||||||
|
const rm = m % 60;
|
||||||
|
return rm ? `${h}h${rm}m` : `${h}h`;
|
||||||
|
}
|
||||||
|
|
||||||
function cellText(v: unknown): string {
|
function cellText(v: unknown): string {
|
||||||
if (v === null || v === undefined) return "";
|
if (v === null || v === undefined) return "";
|
||||||
if (typeof v === "object") return JSON.stringify(v);
|
if (typeof v === "object") return JSON.stringify(v);
|
||||||
|
|
@ -1056,7 +1073,8 @@ export function BizStatePage() {
|
||||||
<th>{t("bizState.colInterval")}</th>
|
<th>{t("bizState.colInterval")}</th>
|
||||||
<th>{t("bizState.scheduleEnabled")}</th>
|
<th>{t("bizState.scheduleEnabled")}</th>
|
||||||
<th>{t("bizState.colStatus")}</th>
|
<th>{t("bizState.colStatus")}</th>
|
||||||
<th>{t("bizState.colLast")}</th>
|
<th>{t("bizState.colStarted")}</th>
|
||||||
|
<th>{t("bizState.colEnded")}</th>
|
||||||
<th>{t("bizState.colActions")}</th>
|
<th>{t("bizState.colActions")}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
@ -1119,7 +1137,15 @@ export function BizStatePage() {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td className="pt-list-time">{fmtTime(row.last_collect_ended_at)}</td>
|
<td className="pt-list-time">{fmtTime(row.last_collect_started_at)}</td>
|
||||||
|
<td className="pt-list-time">
|
||||||
|
{fmtTime(row.last_collect_ended_at)}
|
||||||
|
{fmtDuration(row.last_collect_started_at, row.last_collect_ended_at) ? (
|
||||||
|
<div className="muted">
|
||||||
|
{fmtDuration(row.last_collect_started_at, row.last_collect_ended_at)}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div className="pt-list-actions">
|
<div className="pt-list-actions">
|
||||||
<Button size="sm" variant="primary" onPress={() => void openTask(row.id, "profiles")}>
|
<Button size="sm" variant="primary" onPress={() => void openTask(row.id, "profiles")}>
|
||||||
|
|
@ -1593,7 +1619,8 @@ export function BizStatePage() {
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style={{ width: 36 }} />
|
<th style={{ width: 36 }} />
|
||||||
<th>{t("bizState.colTime")}</th>
|
<th>{t("bizState.colStarted")}</th>
|
||||||
|
<th>{t("bizState.colEnded")}</th>
|
||||||
<th>{t("bizState.colAlias")}</th>
|
<th>{t("bizState.colAlias")}</th>
|
||||||
<th>{t("bizState.colStatus")}</th>
|
<th>{t("bizState.colStatus")}</th>
|
||||||
<th>{t("bizState.colProtect")}</th>
|
<th>{t("bizState.colProtect")}</th>
|
||||||
|
|
@ -1615,6 +1642,12 @@ export function BizStatePage() {
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td className="pt-list-time">{fmtTime(b.started_at)}</td>
|
<td className="pt-list-time">{fmtTime(b.started_at)}</td>
|
||||||
|
<td className="pt-list-time">
|
||||||
|
{fmtTime(b.ended_at)}
|
||||||
|
{fmtDuration(b.started_at, b.ended_at) ? (
|
||||||
|
<div className="muted">{fmtDuration(b.started_at, b.ended_at)}</div>
|
||||||
|
) : null}
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
|
@ -1896,7 +1929,11 @@ export function BizStatePage() {
|
||||||
})}
|
})}
|
||||||
{" · "}
|
{" · "}
|
||||||
{batchDetail.command_count} cmd · {batchDetail.row_count} rows ·{" "}
|
{batchDetail.command_count} cmd · {batchDetail.row_count} rows ·{" "}
|
||||||
{fmtTime(batchDetail.started_at)}
|
{t("bizState.colStarted")} {fmtTime(batchDetail.started_at)} ·{" "}
|
||||||
|
{t("bizState.colEnded")} {fmtTime(batchDetail.ended_at)}
|
||||||
|
{fmtDuration(batchDetail.started_at, batchDetail.ended_at)
|
||||||
|
? ` · ${fmtDuration(batchDetail.started_at, batchDetail.ended_at)}`
|
||||||
|
: ""}
|
||||||
</span>
|
</span>
|
||||||
<div className="bs-id-row" title={String(batchDetail.id || "")}>
|
<div className="bs-id-row" title={String(batchDetail.id || "")}>
|
||||||
<span className="bs-id-row__label">{t("bizState.batchId")}</span>
|
<span className="bs-id-row__label">{t("bizState.batchId")}</span>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue