fix: avoid blocking sentinel on terminal timing correction (#992)
Co-authored-by: Codex <codex@noreply.local>
This commit is contained in:
@@ -571,3 +571,5 @@ Dashboard 增强执行 issue 为 [#935](https://github.com/pikasTech/unidesk/iss
|
||||
P7 P6 收口必须区分 public dashboard validation 与 targetValidation quick verify:`monitor.pikapython.com` root/CSS/JS 200 只证明公开入口和静态 dashboard 资源可用;quick verify 的 `observe command`、采样样本、analyze report 和 red finding 仍是业务恢复判定的一部分。若 quick verify 因 `observe-command-newSession-failed`、`no-samples` 或等价采样器控制失败而 blocked,P6 issue 必须保持未关闭或显式拆出后续 blocker,不得只凭 public dashboard 200 关闭。
|
||||
|
||||
P8 哨兵恢复执行 issue 为 [#971](https://github.com/pikasTech/unidesk/issues/971)。P8 closeout 必须回写:SPEC P8 引用、120s warning 证据、`quick-verify-no-business-turn` 或等价业务触达证据、`browser-timeout` 分类修正、中文运维页面验证、`monitor.pikapython.com` 公网入口验证、k3s 内部 Service DNS quick verify 路径、D601/v03 用户入口 smoke 结果,以及仍未解除的真实业务 blocker 是否已单独拆出。
|
||||
|
||||
P8-P8 起,targetValidation 的 availability blocker 与 Workbench timing 架构治理必须分层。若同一 trace 在 terminal 前最后一帧仍为 running,随后 terminal commit 的 sealed `durationMs` 把可见 `totalElapsed` 小幅校正到更短值,且 drop 不超过 YAML `turnTimingSampleSlackSeconds`、final response 与完成行均已可见,则该现象作为 terminal-boundary timing correction 证据保留,不生成 `turn-timing-total-elapsed-decrease` red blocker。归零、running/running 下降、terminal 后增长、完成耗时与卡片耗时超出 slack、trace 乱序和完成行非最后仍保持 red;根因治理继续归 [HWLAB #2055](https://github.com/pikasTech/HWLAB/issues/2055) 和 [HWLAB #2125](https://github.com/pikasTech/HWLAB/issues/2125),不得在 UI、CLI renderer 或 analyzer 中做读侧 repair。
|
||||
|
||||
@@ -91,6 +91,7 @@ export function nodeWebObserveAnalyzerTimingSource(): string {
|
||||
elapsedZeroResets: timingEvents.elapsedZeroResets,
|
||||
totalElapsedForwardJumps: timingEvents.totalElapsedForwardJumps,
|
||||
terminalElapsedGrowth: timingEvents.terminalElapsedGrowth,
|
||||
terminalElapsedCorrections: timingEvents.terminalElapsedCorrections,
|
||||
recentUpdateResets: timingEvents.recentUpdateResets,
|
||||
recentUpdateSteps: timingEvents.recentUpdateSteps
|
||||
};
|
||||
@@ -120,6 +121,7 @@ function detectTurnTimingNonMonotonic(columns, rows) {
|
||||
const elapsedZeroResets = [];
|
||||
const totalElapsedForwardJumps = [];
|
||||
const terminalElapsedGrowth = [];
|
||||
const terminalElapsedCorrections = [];
|
||||
const recentUpdateResets = [];
|
||||
const recentUpdateSteps = [];
|
||||
for (const column of columns) {
|
||||
@@ -135,6 +137,9 @@ function detectTurnTimingNonMonotonic(columns, rows) {
|
||||
const previous = previousByMetric.get(metric);
|
||||
if (previous && metric === "totalElapsedSeconds" && current < previous.value) {
|
||||
const anomaly = previous.value > 0 && current === 0 ? "zero-reset" : "decrease";
|
||||
const terminalTransition = !isTerminalTurnStatus(previous.status) && isTerminalTurnStatus(cell.status);
|
||||
const dropSeconds = previous.value - current;
|
||||
const allowedDropSeconds = Math.max(1, Number(alertThresholds?.turnTimingSampleSlackSeconds || 0));
|
||||
const event = {
|
||||
columnId: column.id,
|
||||
columnLabel: column.label,
|
||||
@@ -144,9 +149,11 @@ function detectTurnTimingNonMonotonic(columns, rows) {
|
||||
fromSeq: previous.seq,
|
||||
fromTs: previous.ts,
|
||||
fromValue: previous.value,
|
||||
fromStatus: previous.status ?? null,
|
||||
toSeq: row.seq ?? null,
|
||||
toTs: row.ts ?? null,
|
||||
toValue: current,
|
||||
toStatus: cell.status ?? null,
|
||||
delta: current - previous.value,
|
||||
traceId: cell.traceId ?? column.traceId ?? null,
|
||||
messageId: cell.messageId ?? column.messageId ?? null,
|
||||
@@ -158,8 +165,17 @@ function detectTurnTimingNonMonotonic(columns, rows) {
|
||||
pageEpoch: cell.pageEpoch ?? row.pageEpoch ?? column.pageEpoch ?? null,
|
||||
valuesRedacted: true
|
||||
};
|
||||
anomalies.push(event);
|
||||
if (anomaly === "zero-reset") elapsedZeroResets.push(event);
|
||||
if (terminalTransition && anomaly === "decrease" && dropSeconds <= allowedDropSeconds) {
|
||||
terminalElapsedCorrections.push({
|
||||
...event,
|
||||
anomaly: "terminal-boundary-correction",
|
||||
expectedPattern: "terminal-sealed-duration-may-correct-running-elapsed-within-slack",
|
||||
allowedDropSeconds,
|
||||
});
|
||||
} else {
|
||||
anomalies.push(event);
|
||||
if (anomaly === "zero-reset") elapsedZeroResets.push(event);
|
||||
}
|
||||
}
|
||||
if (previous && metric === "totalElapsedSeconds" && current > previous.value) {
|
||||
const sampleDeltaSeconds = elapsedSecondsBetween(previous.ts, row.ts);
|
||||
@@ -319,7 +335,7 @@ function detectTurnTimingNonMonotonic(columns, rows) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return { anomalies, elapsedZeroResets, totalElapsedForwardJumps, terminalElapsedGrowth, recentUpdateResets, recentUpdateSteps };
|
||||
return { anomalies, elapsedZeroResets, totalElapsedForwardJumps, terminalElapsedGrowth, terminalElapsedCorrections, recentUpdateResets, recentUpdateSteps };
|
||||
}
|
||||
|
||||
function elapsedSecondsBetween(fromTs, toTs) {
|
||||
|
||||
Reference in New Issue
Block a user