惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IT之家
IT之家
Engineering at Meta
Engineering at Meta
腾讯CDC
宝玉的分享
宝玉的分享
H
Help Net Security
I
InfoQ
博客园 - Franky
The GitHub Blog
The GitHub Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Microsoft Security Blog
Microsoft Security Blog
M
MIT News - Artificial intelligence
博客园_首页
美团技术团队
Recent Announcements
Recent Announcements
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
雷峰网
雷峰网
The Cloudflare Blog
博客园 - 司徒正美
Vercel News
Vercel News
MyScale Blog
MyScale Blog
人人都是产品经理
人人都是产品经理
爱范儿
爱范儿
月光博客
月光博客

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
fix: carry gateway restart trace across respawn (#82396) ...
steipete · 2026-05-16 · via Recent Commits to openclaw:main

@@ -3,16 +3,27 @@ import { isTruthyEnvValue } from "../infra/env.js";

33

import { createSubsystemLogger } from "../logging/subsystem.js";

4455

const restartTraceLog = createSubsystemLogger("gateway");

6+

const RESTART_TRACE_HANDOFF_STARTED_AT_ENV = "OPENCLAW_GATEWAY_RESTART_TRACE_STARTED_AT_MS";

7+

const RESTART_TRACE_HANDOFF_LAST_AT_ENV = "OPENCLAW_GATEWAY_RESTART_TRACE_LAST_AT_MS";

8+

const RESTART_TRACE_HANDOFF_MAX_AGE_MS = 10 * 60_000;

69710

type RestartTraceMetricValue = boolean | number | string | null | undefined;

811

type RestartTraceMetrics =

912

| Readonly<Record<string, RestartTraceMetricValue>>

1013

| ReadonlyArray<readonly [string, RestartTraceMetricValue]>;

14+

export type GatewayRestartTraceHandoff = {

15+

startedAt: number;

16+

lastAt: number;

17+

};

11181219

let startedAt = 0;

1320

let lastAt = 0;

1421

let active = false;

152223+

function nowMs(): number {

24+

return performance.timeOrigin + performance.now();

25+

}

26+1627

function isRestartTraceEnabled(): boolean {

1728

return isTruthyEnvValue(process.env.OPENCLAW_GATEWAY_RESTART_TRACE);

1829

}

@@ -91,7 +102,7 @@ export function startGatewayRestartTrace(name: string, metrics?: RestartTraceMet

91102

active = false;

92103

return;

93104

}

94-

const now = performance.now();

105+

const now = nowMs();

95106

startedAt = now;

96107

lastAt = now;

97108

active = true;

@@ -106,7 +117,7 @@ export function markGatewayRestartTrace(name: string, metrics?: RestartTraceMetr

106117

if (!isGatewayRestartTraceActive()) {

107118

return;

108119

}

109-

const now = performance.now();

120+

const now = nowMs();

110121

emitRestartTrace(name, now - lastAt, now - startedAt, metrics);

111122

lastAt = now;

112123

}

@@ -124,11 +135,11 @@ export async function measureGatewayRestartTrace<T>(

124135

if (!isGatewayRestartTraceActive()) {

125136

return await run();

126137

}

127-

const before = performance.now();

138+

const before = nowMs();

128139

try {

129140

return await run();

130141

} finally {

131-

const now = performance.now();

142+

const now = nowMs();

132143

emitRestartTrace(

133144

name,

134145

now - before,

@@ -147,7 +158,7 @@ export function recordGatewayRestartTrace(

147158

if (!isGatewayRestartTraceActive() || !Number.isFinite(durationMs)) {

148159

return;

149160

}

150-

const now = performance.now();

161+

const now = nowMs();

151162

emitRestartTrace(name, Math.max(0, durationMs), now - startedAt, metrics);

152163

lastAt = now;

153164

}

@@ -183,6 +194,87 @@ export function collectGatewayProcessMemoryUsageMb(): ReadonlyArray<readonly [st

183194

];

184195

}

185196197+

function normalizeRestartTraceHandoff(value: unknown): GatewayRestartTraceHandoff | null {

198+

if (typeof value !== "object" || value === null || Array.isArray(value)) {

199+

return null;

200+

}

201+

const record = value as { startedAt?: unknown; lastAt?: unknown };

202+

if (

203+

typeof record.startedAt !== "number" ||

204+

!Number.isFinite(record.startedAt) ||

205+

typeof record.lastAt !== "number" ||

206+

!Number.isFinite(record.lastAt) ||

207+

record.startedAt <= 0 ||

208+

record.lastAt < record.startedAt ||

209+

record.lastAt - record.startedAt > RESTART_TRACE_HANDOFF_MAX_AGE_MS

210+

) {

211+

return null;

212+

}

213+

const now = nowMs();

214+

if (record.startedAt > now || now - record.startedAt > RESTART_TRACE_HANDOFF_MAX_AGE_MS) {

215+

return null;

216+

}

217+

return {

218+

startedAt: record.startedAt,

219+

lastAt: record.lastAt,

220+

};

221+

}

222+223+

export function captureGatewayRestartTraceHandoff(): GatewayRestartTraceHandoff | undefined {

224+

if (!isGatewayRestartTraceActive()) {

225+

return undefined;

226+

}

227+

return { startedAt, lastAt };

228+

}

229+230+

export function createGatewayRestartTraceHandoffEnv(

231+

handoff: GatewayRestartTraceHandoff | undefined = captureGatewayRestartTraceHandoff(),

232+

): NodeJS.ProcessEnv | undefined {

233+

const normalized = normalizeRestartTraceHandoff(handoff);

234+

if (!normalized) {

235+

return undefined;

236+

}

237+

return {

238+

[RESTART_TRACE_HANDOFF_STARTED_AT_ENV]: String(normalized.startedAt),

239+

[RESTART_TRACE_HANDOFF_LAST_AT_ENV]: String(normalized.lastAt),

240+

};

241+

}

242+243+

export function resumeGatewayRestartTraceFromHandoff(

244+

handoff: unknown,

245+

metrics?: RestartTraceMetrics,

246+

): boolean {

247+

if (!isRestartTraceEnabled() || active) {

248+

return false;

249+

}

250+

const normalized = normalizeRestartTraceHandoff(handoff);

251+

if (!normalized) {

252+

return false;

253+

}

254+

startedAt = normalized.startedAt;

255+

lastAt = normalized.lastAt;

256+

active = true;

257+

markGatewayRestartTrace("restart.process-resume", metrics);

258+

return true;

259+

}

260+261+

export function resumeGatewayRestartTraceFromEnv(

262+

env: NodeJS.ProcessEnv = process.env,

263+

metrics?: RestartTraceMetrics,

264+

): boolean {

265+

const startedRaw = env[RESTART_TRACE_HANDOFF_STARTED_AT_ENV];

266+

const lastRaw = env[RESTART_TRACE_HANDOFF_LAST_AT_ENV];

267+

delete env[RESTART_TRACE_HANDOFF_STARTED_AT_ENV];

268+

delete env[RESTART_TRACE_HANDOFF_LAST_AT_ENV];

269+

return resumeGatewayRestartTraceFromHandoff(

270+

{

271+

startedAt: Number(startedRaw),

272+

lastAt: Number(lastRaw),

273+

},

274+

metrics,

275+

);

276+

}

277+186278

export function resetGatewayRestartTraceForTest(): void {

187279

startedAt = 0;

188280

lastAt = 0;