mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 07:40:44 +00:00
fix(gateway): route watch trace spam to artifacts
This commit is contained in:
@@ -9,6 +9,8 @@ const TMUX_ATTACH_FORCE_VALUES = new Set(["1", "true", "yes", "on"]);
|
||||
const DEFAULT_PROFILE_NAME = "main";
|
||||
const DEFAULT_BENCHMARK_PROFILE_DIR = ".artifacts/gateway-watch-profiles";
|
||||
const RUN_NODE_CPU_PROF_DIR_ENV = "OPENCLAW_RUN_NODE_CPU_PROF_DIR";
|
||||
const RUN_NODE_OUTPUT_LOG_ENV = "OPENCLAW_RUN_NODE_OUTPUT_LOG";
|
||||
const RUN_NODE_FILTER_SYNC_IO_STDERR_ENV = "OPENCLAW_RUN_NODE_FILTER_SYNC_IO_STDERR";
|
||||
const RAW_WATCH_SCRIPT = "scripts/watch-node.mjs";
|
||||
const TMUX_CWD_ENV_KEY = "OPENCLAW_GATEWAY_WATCH_CWD";
|
||||
const TMUX_CWD_OPTION_KEY = "@openclaw.gateway_watch.cwd";
|
||||
@@ -19,6 +21,8 @@ const TMUX_CHILD_ENV_KEYS = [
|
||||
"OPENCLAW_HOME",
|
||||
"OPENCLAW_PROFILE",
|
||||
RUN_NODE_CPU_PROF_DIR_ENV,
|
||||
RUN_NODE_FILTER_SYNC_IO_STDERR_ENV,
|
||||
RUN_NODE_OUTPUT_LOG_ENV,
|
||||
"OPENCLAW_SKIP_CHANNELS",
|
||||
"OPENCLAW_STATE_DIR",
|
||||
"OPENCLAW_TRACE_SYNC_IO",
|
||||
@@ -50,6 +54,11 @@ const readArgValue = (args, flag) => {
|
||||
return null;
|
||||
};
|
||||
|
||||
const joinArtifactPath = (dir, basename) => {
|
||||
const normalizedDir = String(dir || DEFAULT_BENCHMARK_PROFILE_DIR).replace(/[\\/]+$/g, "");
|
||||
return `${normalizedDir || "."}/${basename}`;
|
||||
};
|
||||
|
||||
const resolveGatewayWatchBenchmarkArgs = ({ args = [], env = process.env } = {}) => {
|
||||
const passthroughArgs = [];
|
||||
let benchmarkDir = null;
|
||||
@@ -98,6 +107,13 @@ const resolveGatewayWatchBenchmarkArgs = ({ args = [], env = process.env } = {})
|
||||
nextEnv[RUN_NODE_CPU_PROF_DIR_ENV] =
|
||||
benchmarkDir || nextEnv[RUN_NODE_CPU_PROF_DIR_ENV] || DEFAULT_BENCHMARK_PROFILE_DIR;
|
||||
nextEnv.OPENCLAW_TRACE_SYNC_IO ??= "0";
|
||||
if (nextEnv.OPENCLAW_TRACE_SYNC_IO === "1") {
|
||||
nextEnv[RUN_NODE_OUTPUT_LOG_ENV] ??= joinArtifactPath(
|
||||
nextEnv[RUN_NODE_CPU_PROF_DIR_ENV],
|
||||
"gateway-watch-output.log",
|
||||
);
|
||||
nextEnv[RUN_NODE_FILTER_SYNC_IO_STDERR_ENV] ??= "1";
|
||||
}
|
||||
}
|
||||
return {
|
||||
args: benchmarkNoForceSeen
|
||||
@@ -105,6 +121,10 @@ const resolveGatewayWatchBenchmarkArgs = ({ args = [], env = process.env } = {})
|
||||
: passthroughArgs,
|
||||
benchmarkNoForce: benchmarkNoForceSeen,
|
||||
benchmarkProfileDir: nextEnv[RUN_NODE_CPU_PROF_DIR_ENV] || null,
|
||||
benchmarkTraceOutputLog:
|
||||
nextEnv[RUN_NODE_FILTER_SYNC_IO_STDERR_ENV] === "1"
|
||||
? nextEnv[RUN_NODE_OUTPUT_LOG_ENV] || null
|
||||
: null,
|
||||
env: nextEnv,
|
||||
};
|
||||
};
|
||||
@@ -250,6 +270,12 @@ export const runGatewayWatchTmuxMain = (params = {}) => {
|
||||
if (resolvedArgs.benchmarkProfileDir) {
|
||||
log(deps.stderr, `gateway:watch benchmark CPU profiles: ${resolvedArgs.benchmarkProfileDir}`);
|
||||
}
|
||||
if (resolvedArgs.benchmarkTraceOutputLog) {
|
||||
log(
|
||||
deps.stderr,
|
||||
`gateway:watch benchmark trace output: ${resolvedArgs.benchmarkTraceOutputLog}`,
|
||||
);
|
||||
}
|
||||
if (resolvedArgs.benchmarkNoForce) {
|
||||
log(deps.stderr, "gateway:watch benchmark running without --force");
|
||||
}
|
||||
|
||||
@@ -386,6 +386,7 @@ const getSignalExitCode = (signal) => (isSignalKey(signal) ? SIGNAL_EXIT_CODES[s
|
||||
|
||||
const RUN_NODE_OUTPUT_LOG_ENV = "OPENCLAW_RUN_NODE_OUTPUT_LOG";
|
||||
const RUN_NODE_CPU_PROF_DIR_ENV = "OPENCLAW_RUN_NODE_CPU_PROF_DIR";
|
||||
const RUN_NODE_FILTER_SYNC_IO_STDERR_ENV = "OPENCLAW_RUN_NODE_FILTER_SYNC_IO_STDERR";
|
||||
const RUN_NODE_BUILD_LOCK_TIMEOUT_ENV = "OPENCLAW_RUN_NODE_BUILD_LOCK_TIMEOUT_MS";
|
||||
const RUN_NODE_BUILD_LOCK_POLL_ENV = "OPENCLAW_RUN_NODE_BUILD_LOCK_POLL_MS";
|
||||
const RUN_NODE_BUILD_LOCK_STALE_ENV = "OPENCLAW_RUN_NODE_BUILD_LOCK_STALE_MS";
|
||||
@@ -585,14 +586,78 @@ const pipeSpawnedOutput = (childProcess, deps) => {
|
||||
if (!deps.outputTee) {
|
||||
return;
|
||||
}
|
||||
const stderrFilter =
|
||||
deps.env[RUN_NODE_FILTER_SYNC_IO_STDERR_ENV] === "1"
|
||||
? createSyncIoTraceStderrFilter(deps)
|
||||
: null;
|
||||
childProcess.stdout?.on("data", (chunk) => {
|
||||
deps.stdout.write(chunk);
|
||||
deps.outputTee.write(chunk);
|
||||
});
|
||||
childProcess.stderr?.on("data", (chunk) => {
|
||||
deps.stderr.write(chunk);
|
||||
if (stderrFilter) {
|
||||
stderrFilter.write(chunk);
|
||||
} else {
|
||||
deps.stderr.write(chunk);
|
||||
}
|
||||
deps.outputTee.write(chunk);
|
||||
});
|
||||
childProcess.stderr?.on("end", () => {
|
||||
stderrFilter?.flush();
|
||||
});
|
||||
};
|
||||
|
||||
const createSyncIoTraceStderrFilter = (deps) => {
|
||||
let buffer = "";
|
||||
let inSyncIoTrace = false;
|
||||
|
||||
const shouldSuppressLine = (line) => {
|
||||
const text = line.replace(/\r?\n$/, "");
|
||||
if (/^\(node:\d+\) WARNING: Detected use of sync API/.test(text)) {
|
||||
inSyncIoTrace = true;
|
||||
return true;
|
||||
}
|
||||
if (!inSyncIoTrace) {
|
||||
return false;
|
||||
}
|
||||
if (text.trim() === "") {
|
||||
inSyncIoTrace = false;
|
||||
return true;
|
||||
}
|
||||
if (/^\s+at\b/.test(text)) {
|
||||
return true;
|
||||
}
|
||||
inSyncIoTrace = false;
|
||||
return false;
|
||||
};
|
||||
|
||||
const writeLine = (line) => {
|
||||
if (!shouldSuppressLine(line)) {
|
||||
deps.stderr.write(line);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
write(chunk) {
|
||||
buffer += String(chunk);
|
||||
while (true) {
|
||||
const newlineIndex = buffer.indexOf("\n");
|
||||
if (newlineIndex === -1) {
|
||||
break;
|
||||
}
|
||||
const line = buffer.slice(0, newlineIndex + 1);
|
||||
buffer = buffer.slice(newlineIndex + 1);
|
||||
writeLine(line);
|
||||
}
|
||||
},
|
||||
flush() {
|
||||
if (!buffer) {
|
||||
return;
|
||||
}
|
||||
writeLine(buffer);
|
||||
buffer = "";
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const closeRunNodeOutputTee = async (deps, exitCode) => {
|
||||
|
||||
Reference in New Issue
Block a user