Align error logging with admin dashboard field conventions

All warn/error log calls now use field names the dashboard's decorate()
function recognizes: `code` for the error code pill, `httpStatus` for the
status badge and severity bucket, `url` for the sidebar link, and
`repoId` for the repository link.

Key changes:
- Streamer errors surface code, httpStatus, url, and nested err in Raw tab
- Nested `{ err: serializeError(e) }` replaced with spread pattern so
  error fields (name, message, status) appear at the top level
- Raw Error objects in catch blocks now go through serializeError()
- Rate limit, token, and PR 404 warnings include code + httpStatus
- Dashboard stack walker traverses both `cause` and `err` chains
- Dashboard Raw tab renders repoId, filePath, upstream*, err, and cause
- trimRawArg recursively trims stacks in nested err/cause chains
- clampPayload strips heavy nested fields before falling back to
  truncated placeholder, preserving flat diagnostic fields
This commit is contained in:
tdurieux
2026-05-07 05:54:18 +03:00
parent b8cfe293ea
commit 9403f15ac3
8 changed files with 63 additions and 18 deletions
+15 -6
View File
@@ -984,13 +984,16 @@ angular
e._method = detail.method || null;
e._repoId = detail.repoId || detail.detail || null;
e._detail = detail.detail && detail.detail !== e._repoId ? detail.detail : null;
// Walk into `cause` to surface the deepest stack — for unhandled
// errors the inner cause is usually the actual JS error frame.
// Walk into `cause` (and `err` for streamer-style entries) to
// surface the deepest stack.
let s = typeof detail.stack === "string" ? detail.stack : null;
let c = detail.cause;
while (!s && c && typeof c === "object") {
if (typeof c.stack === "string") s = c.stack;
c = c.cause;
var roots = [detail.cause, detail.err].filter(Boolean);
for (var ri = 0; !s && ri < roots.length; ri++) {
var c = roots[ri];
while (!s && c && typeof c === "object") {
if (typeof c.stack === "string") s = c.stack;
c = c.cause;
}
}
e._stack = s;
} else {
@@ -1037,7 +1040,13 @@ angular
}
}
push("detail", detailValue);
push("repoId", detail && detail.repoId);
push("filePath", detail && detail.filePath);
push("upstreamStatus", detail && detail.upstreamStatus);
push("upstreamBody", detail && detail.upstreamBody);
push("url", entry._url);
push("err", detail && detail.err);
push("cause", detail && !detail.err && detail.cause);
push("ts", entry.ts);
if (!fields.length) return JSON.stringify(entry, null, 2);
const keyW = fields.reduce((w, f) => Math.max(w, f[0].length), 0);