Skip to content

Commit 005cc2a

Browse files
committed
fix(test): scan QA Lab stdout artifacts incrementally
1 parent c917f1b commit 005cc2a

2 files changed

Lines changed: 35 additions & 21 deletions

File tree

test/e2e/qa-lab/runtime/qa-otel-smoke-runtime.ts

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ const MAX_STDOUT_DIAGNOSTIC_LINE_BYTES = readPositiveIntegerEnv(
158158
"OPENCLAW_QA_OTEL_MAX_STDOUT_DIAGNOSTIC_LINE_BYTES",
159159
512 * 1024,
160160
);
161+
const GATEWAY_STDOUT_ARTIFACT_READ_CHUNK_BYTES = 64 * 1024;
161162

162163
function readPositiveIntegerEnv(
163164
name: string,
@@ -1075,8 +1076,10 @@ async function appendGatewayStdoutArtifactLogs(params: {
10751076
"gateway.stdout.log",
10761077
);
10771078
try {
1078-
params.capture.append(
1079-
await readUtf8FileTail(gatewayStdoutPath, MAX_STDOUT_DIAGNOSTIC_LINE_BYTES),
1079+
await appendUtf8FileToStdoutDiagnosticCapture(
1080+
gatewayStdoutPath,
1081+
params.capture,
1082+
GATEWAY_STDOUT_ARTIFACT_READ_CHUNK_BYTES,
10801083
);
10811084
params.capture.flush();
10821085
} catch (error) {
@@ -1086,22 +1089,21 @@ async function appendGatewayStdoutArtifactLogs(params: {
10861089
}
10871090
}
10881091

1089-
async function readUtf8FileTail(filePath: string, maxBytes: number): Promise<string> {
1092+
async function appendUtf8FileToStdoutDiagnosticCapture(
1093+
filePath: string,
1094+
capture: ReturnType<typeof createStdoutDiagnosticLogCapture>,
1095+
chunkBytes = GATEWAY_STDOUT_ARTIFACT_READ_CHUNK_BYTES,
1096+
): Promise<void> {
10901097
const file = await open(filePath, "r");
10911098
try {
1092-
const stats = await file.stat();
1093-
const bytesToRead = Math.min(stats.size, Math.max(1, maxBytes));
1094-
const buffer = Buffer.alloc(bytesToRead);
1095-
const start = stats.size - bytesToRead;
1096-
let offset = 0;
1097-
while (offset < bytesToRead) {
1098-
const { bytesRead } = await file.read(buffer, offset, bytesToRead - offset, start + offset);
1099+
const buffer = Buffer.alloc(Math.max(1, chunkBytes));
1100+
for (;;) {
1101+
const { bytesRead } = await file.read(buffer, 0, buffer.length);
10991102
if (bytesRead === 0) {
11001103
break;
11011104
}
1102-
offset += bytesRead;
1105+
capture.append(buffer.subarray(0, bytesRead));
11031106
}
1104-
return buffer.subarray(0, offset).toString("utf8");
11051107
} finally {
11061108
await file.close();
11071109
}
@@ -1909,12 +1911,13 @@ export const testing = {
19091911
appendCapturedBodyText,
19101912
assertSmoke,
19111913
createBoundedTextAccumulator,
1914+
createStdoutDiagnosticLogCapture,
19121915
decodeRequestBody,
19131916
parseArgs,
19141917
parseStdoutDiagnosticLogLine,
19151918
readPositiveIntegerEnv,
19161919
readRequestBody,
1917-
readUtf8FileTail,
1920+
appendUtf8FileToStdoutDiagnosticCapture,
19181921
startLocalOtlpReceiver,
19191922
startDockerOtelCollector,
19201923
terminateChildTree,

test/e2e/qa-lab/runtime/qa-otel-smoke.e2e.test.ts

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -501,19 +501,30 @@ describe("qa-otel-smoke receiver bounds", () => {
501501
expect(output.text()).not.toContain("DO_NOT_RETAIN_COLLECTOR_PREFIX");
502502
});
503503

504-
it("reads only a bounded tail from gateway stdout artifacts", async () => {
505-
const tempRoot = mkdtempSync(path.join(os.tmpdir(), "openclaw-qa-otel-stdout-tail-"));
504+
it("streams gateway stdout artifact records without requiring them in the tail", async () => {
505+
const tempRoot = mkdtempSync(path.join(os.tmpdir(), "openclaw-qa-otel-stdout-stream-"));
506506
const logPath = path.join(tempRoot, "gateway.stdout.log");
507+
const capture = testing.createStdoutDiagnosticLogCapture();
508+
const record = {
509+
signal: "openclaw.diagnostic.log",
510+
ts: "2026-06-18T00:00:00.000Z",
511+
"service.name": "openclaw-qa-lab-otel-smoke",
512+
severityText: "INFO",
513+
severityNumber: 9,
514+
body: "early log",
515+
attributes: {},
516+
};
507517
try {
508518
writeFileSync(
509519
logPath,
510-
`DO_NOT_RETAIN_GATEWAY_STDOUT_PREFIX\n${"x".repeat(2048)}\nGATEWAY_STDOUT_TAIL\n`,
520+
`${JSON.stringify(record)}\n${"x".repeat(256 * 1024)}\nGATEWAY_STDOUT_TAIL\n`,
511521
);
512522

513-
const text = await testing.readUtf8FileTail(logPath, 64);
523+
await testing.appendUtf8FileToStdoutDiagnosticCapture(logPath, capture);
524+
capture.flush();
514525

515-
expect(text).toContain("GATEWAY_STDOUT_TAIL");
516-
expect(text).not.toContain("DO_NOT_RETAIN_GATEWAY_STDOUT_PREFIX");
526+
expect(capture.records).toEqual([record]);
527+
expect(capture.lines).toHaveLength(1);
517528
} finally {
518529
rmSync(tempRoot, { force: true, recursive: true });
519530
}
@@ -536,14 +547,14 @@ describe("qa-otel-smoke receiver bounds", () => {
536547
mkdirSync(artifactDir, { recursive: true });
537548
writeFileSync(
538549
path.join(artifactDir, "gateway.stdout.log"),
539-
`DO_NOT_RETAIN_GATEWAY_STDOUT_PREFIX\n${"x".repeat(2048)}\n${JSON.stringify(record)}\n`,
550+
`${JSON.stringify(record)}\n${"x".repeat(256 * 1024)}\n`,
540551
);
541552
const capture = testing.createStdoutDiagnosticLogCapture();
542553

543554
await testing.appendGatewayStdoutArtifactLogs({ capture, outputDir });
544555

545556
expect(capture.records).toEqual([record]);
546-
expect(capture.lines.join("\n")).not.toContain("DO_NOT_RETAIN_GATEWAY_STDOUT_PREFIX");
557+
expect(capture.lines).toHaveLength(1);
547558
} finally {
548559
rmSync(tempRoot, { force: true, recursive: true });
549560
}

0 commit comments

Comments
 (0)