Improve error handling

This commit is contained in:
tdurieux
2026-05-06 16:45:22 +03:00
parent 3613c895c8
commit dcb524c8c1
10 changed files with 72 additions and 12 deletions
+1 -1
View File
File diff suppressed because one or more lines are too long
+7
View File
@@ -5068,6 +5068,13 @@ body {
max-height: 22em; overflow: auto;
box-shadow: var(--card-shadow);
}
.errors-page .stack-pre {
/* Stack frames look better with a tighter line-height than the curated
JSON view, since each frame is a single readable line. */
line-height: 1.45;
white-space: pre;
overflow-x: auto;
}
.errors-page .related-row {
display: flex; gap: 10px; padding: 6px 12px; align-items: center;
border-bottom: 1px solid var(--border-soft);
+2
View File
@@ -148,11 +148,13 @@
<div class="errors-row-detail" ng-if="expanded[row._key]">
<div class="detail-tabs">
<button type="button" ng-class="{active: detailTab[row._key] === 'raw' || !detailTab[row._key]}" ng-click="detailTab[row._key] = 'raw'">Raw</button>
<button type="button" ng-class="{active: detailTab[row._key] === 'stack'}" ng-click="detailTab[row._key] = 'stack'" ng-if="row._stack">Stack</button>
<button type="button" ng-class="{active: detailTab[row._key] === 'related'}" ng-click="detailTab[row._key] = 'related'" ng-if="row.count > 1">Related ({{row.count}})</button>
</div>
<div class="detail-body">
<div class="detail-main">
<pre ng-if="(detailTab[row._key] || 'raw') === 'raw'">{{row._detailJson}}</pre>
<pre ng-if="detailTab[row._key] === 'stack'" class="stack-pre">{{row._stack}}</pre>
<div ng-if="detailTab[row._key] === 'related'" class="related-list">
<div class="related-row" ng-repeat="r in row._related track by $index">
<span class="when-abs">{{absTimeShort(r.ts)}}</span>
+28 -1
View File
@@ -943,6 +943,16 @@ angular
} else if (detail.code && errorKeyRe.test(String(detail.code))) {
e.displayMessage = String(detail.code);
e.displayContext = e.message;
} else if (
detail.name &&
detail.name !== "AnonymousError" &&
detail.name !== "Error"
) {
// Plain JS errors (SyntaxError, TypeError, RangeError, ...) — use
// the class name as the visible code; the original message is
// shown as italic context.
e.displayMessage = detail.name;
e.displayContext = detail.message || e.message;
} else {
e.displayMessage = e.message;
}
@@ -951,10 +961,20 @@ 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.
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;
}
e._stack = s;
} else {
e.displayMessage = e.message;
e._status = null;
e._url = null;
e._stack = null;
}
e._bucket = bucketFor(detail, e.level);
e._detailJson = renderDisplayPayload(e, detail);
@@ -1138,9 +1158,16 @@ angular
}
function loadEntries(append) {
// On auto-refresh after the user has paginated ("Load older"),
// request the SAME-sized window from the head so we don't blow away
// their loaded tail. Newer entries take the top, the oldest visible
// ones drop off naturally as the redis list rotates.
const offset = append ? $scope.entries.length : 0;
const limit = append
? $scope.pageSize
: Math.max($scope.pageSize, $scope.entries.length || $scope.pageSize);
$http
.get("/api/admin/errors", { params: { offset, limit: $scope.pageSize } })
.get("/api/admin/errors", { params: { offset, limit } })
.then(
(res) => {
const next = (res.data.entries || []).map(decorate);
+1 -1
View File
File diff suppressed because one or more lines are too long