|
1 | 1 | // QA OTEL Smoke tests cover QA Lab telemetry evidence. |
2 | 2 | import { spawn, spawnSync } from "node:child_process"; |
3 | 3 | import { EventEmitter } from "node:events"; |
4 | | -import { existsSync, mkdirSync, mkdtempSync, rmSync, statSync } from "node:fs"; |
| 4 | +import { existsSync, mkdirSync, mkdtempSync, rmSync, statSync, writeFileSync } from "node:fs"; |
5 | 5 | import { createConnection as createNetConnection } from "node:net"; |
6 | 6 | import os from "node:os"; |
7 | 7 | import path from "node:path"; |
@@ -501,6 +501,65 @@ describe("qa-otel-smoke receiver bounds", () => { |
501 | 501 | expect(output.text()).not.toContain("DO_NOT_RETAIN_COLLECTOR_PREFIX"); |
502 | 502 | }); |
503 | 503 |
|
| 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-")); |
| 506 | + 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 | + }; |
| 517 | + try { |
| 518 | + writeFileSync( |
| 519 | + logPath, |
| 520 | + `${JSON.stringify(record)}\n${"x".repeat(256 * 1024)}\nGATEWAY_STDOUT_TAIL\n`, |
| 521 | + ); |
| 522 | + |
| 523 | + await testing.appendUtf8FileToStdoutDiagnosticCapture(logPath, capture); |
| 524 | + capture.flush(); |
| 525 | + |
| 526 | + expect(capture.records).toEqual([record]); |
| 527 | + expect(capture.lines).toHaveLength(1); |
| 528 | + } finally { |
| 529 | + rmSync(tempRoot, { force: true, recursive: true }); |
| 530 | + } |
| 531 | + }); |
| 532 | + |
| 533 | + it("keeps gateway stdout artifact fallback parsing bounded", async () => { |
| 534 | + const tempRoot = mkdtempSync(path.join(os.tmpdir(), "openclaw-qa-otel-stdout-artifact-")); |
| 535 | + const outputDir = path.join(tempRoot, "output"); |
| 536 | + const artifactDir = path.join(outputDir, "artifacts", "gateway-runtime"); |
| 537 | + const record = { |
| 538 | + signal: "openclaw.diagnostic.log", |
| 539 | + ts: "2026-06-18T00:00:00.000Z", |
| 540 | + "service.name": "openclaw-qa-lab-otel-smoke", |
| 541 | + severityText: "INFO", |
| 542 | + severityNumber: 9, |
| 543 | + body: "tail log", |
| 544 | + attributes: {}, |
| 545 | + }; |
| 546 | + try { |
| 547 | + mkdirSync(artifactDir, { recursive: true }); |
| 548 | + writeFileSync( |
| 549 | + path.join(artifactDir, "gateway.stdout.log"), |
| 550 | + `${JSON.stringify(record)}\n${"x".repeat(256 * 1024)}\n`, |
| 551 | + ); |
| 552 | + const capture = testing.createStdoutDiagnosticLogCapture(); |
| 553 | + |
| 554 | + await testing.appendGatewayStdoutArtifactLogs({ capture, outputDir }); |
| 555 | + |
| 556 | + expect(capture.records).toEqual([record]); |
| 557 | + expect(capture.lines).toHaveLength(1); |
| 558 | + } finally { |
| 559 | + rmSync(tempRoot, { force: true, recursive: true }); |
| 560 | + } |
| 561 | + }); |
| 562 | + |
504 | 563 | it("times out and kills a wedged QA suite child with a detached gateway", async () => { |
505 | 564 | if (process.platform === "win32") { |
506 | 565 | return; |
|
0 commit comments