openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
108 lines (107 loc) • 2.87 kB
JavaScript
import { n as createQueuedDiagnosticPhaseEmitter } from "./diagnostic-events-DT4ejwoa.mjs";
import { performance } from "node:perf_hooks";
//#region src/gateway/server-methods/chat-send-diagnostics.ts
const PHASES = [
"authority",
"admission",
"preparation",
"attachments",
"replyContext",
"authoring",
"persist",
"runAdmission",
"replyInitialization",
"snapshot",
"worktree",
"effects",
"response",
"dispatch"
];
const requestDiagnostics = /* @__PURE__ */ new WeakMap();
/** Internal request attachment; handler spans do not expand the public plugin options. */
function bindChatSendDiagnostics(request, diagnostics) {
if (diagnostics) requestDiagnostics.set(request, diagnostics);
}
function readChatSendDiagnostics(request) {
return requestDiagnostics.get(request);
}
/** Request-owned totals; nested and parallel phases can overlap. */
function startChatSendDiagnostics(log) {
const emit = createQueuedDiagnosticPhaseEmitter();
const totals = /* @__PURE__ */ new Map();
const active = /* @__PURE__ */ new Set();
let stage = "request";
let startedAt = performance.now();
let acknowledgedMs;
let finished = false;
const report = () => {
const now = performance.now();
for (const flush of active) flush(now);
const elapsedMs = now - startedAt;
const endedAt = Date.now();
try {
let message = `slow chat send ${Math.round(elapsedMs)}ms stage=${stage}`;
if (acknowledgedMs !== void 0) message += ` ack=${Math.round(acknowledgedMs)}ms`;
for (const phase of PHASES) {
const durationMs = totals.get(phase);
if (durationMs === void 0) continue;
emit?.({
name: `chat.send.${phase}`,
startedAt: endedAt - elapsedMs,
endedAt,
durationMs,
details: { stage }
});
message += ` ${phase}=${Math.round(durationMs)}ms`;
}
if (elapsedMs >= 1e3) log.info(message);
} catch {}
totals.clear();
startedAt = now;
return elapsedMs;
};
const finish = () => {
if (!finished) {
report();
finished = true;
active.clear();
}
};
return {
scope(initialPhase) {
if (finished) return;
let phase = initialPhase;
let phaseStartedAt = performance.now();
const flush = (now) => {
if (phase) totals.set(phase, (totals.get(phase) ?? 0) + now - phaseStartedAt);
phaseStartedAt = now;
};
active.add(flush);
const scope = {
mark(nextPhase) {
if (active.has(flush)) {
flush(performance.now());
phase = nextPhase;
}
},
finish() {
scope.mark();
active.delete(flush);
}
};
return scope;
},
acknowledge() {
if (!finished && stage === "request") {
acknowledgedMs = report();
stage = "startup";
}
},
finish,
[Symbol.dispose]() {
if (stage === "request") finish();
}
};
}
//#endregion
export { readChatSendDiagnostics as n, startChatSendDiagnostics as r, bindChatSendDiagnostics as t };