diff --git a/scripts/check-production-logs.js b/scripts/check-production-logs.js index dc77d27..feead60 100644 --- a/scripts/check-production-logs.js +++ b/scripts/check-production-logs.js @@ -8,6 +8,7 @@ function logSummary() { function observeLine(summary, line) { // Older releases rely on Node's stderr. New releases also emit a redacted // process_fatal_error event before Node terminates. + if (/ECONNRESET|socket hang up/i.test(line)) summary.connectionResets++; const match = /^\S+ (INFO|WARN|ERROR) \[([^\]]+)\] .*? (\{.*\})$/.exec(line); if (!match) { if (/Unhandled ['"]error['"] event|unhandled(?:promise)?rejection|FATAL ERROR|heap out of memory/i.test(line)) summary.fatalErrors++; @@ -26,7 +27,6 @@ function observeLine(summary, line) { else summary.interrupted++; if (data.status === 429) summary.rateLimited++; } - if (/ECONNRESET|socket hang up/i.test(line)) summary.connectionResets++; } async function readLogs(name, since) { const summary = logSummary(); diff --git a/test/github-app.test.js b/test/github-app.test.js index 6b92ea6..a1fb00d 100644 --- a/test/github-app.test.js +++ b/test/github-app.test.js @@ -95,7 +95,11 @@ describe("GitHub App protocol boundaries", () => { const GitHubStream = require("../src/core/source/GitHubStream").default; const source = Object.create(GitHubStream.prototype); source.data = { organization: "other", repoName: "public", commit: "abc" }; - await source.downloadWithFallback(handle, "blob", "README.md"); + const content = await source.downloadWithFallback(handle, "blob", "README.md"); + expect(captured).to.equal(undefined); + let body = ""; + for await (const chunk of content) body += chunk; + expect(body).to.equal("file"); expect(captured.url).to.include("other/public"); expect(captured.url).to.include("README.md"); expect(captured.options.headers.authorization).to.equal(undefined); diff --git a/test/production-failure-fixes.test.js b/test/production-failure-fixes.test.js index d1e35a8..f9646ab 100644 --- a/test/production-failure-fixes.test.js +++ b/test/production-failure-fixes.test.js @@ -122,6 +122,15 @@ describe("production failure fixes", function () { expect(res.statusCode).to.equal(429); expect(res.body).to.deep.equal({ error: "rate_limited", resetAt }); expect(Number(headers["Retry-After"])).to.be.within(9, 10); }); + it("counts native and structured connection reset lines once each", () => { + const summary = logSummary(); + observeLine(summary, "Error: read ECONNRESET"); + observeLine(summary, "Error: socket hang up"); + observeLine(summary, '2026-10-09T00:00:00Z ERROR [process] process fatal error {"code":"process_fatal_error","message":"read ECONNRESET"}'); + observeLine(summary, "ordinary native output"); + expect(summary.connectionResets).to.equal(3); + expect(summary.fatalErrors).to.equal(1); + }); it("flags native unhandled stream errors and restarts without reporting private log fields", () => { const summary = logSummary(); observeLine(summary, "throw er; // Unhandled 'error' event");