Correct bucket latency telemetry (PR 1282, 398598e)
CI / lint (pull_request) Successful in 6m20s
CI / build-release (pull_request) Successful in 12s
CI / browser-journey (pull_request) Failing after 10m12s
CI / release-candidate (pull_request) Has been skipped

- Render bucket latency rows inside #bucket-latency-rows (never replace
  panel); preserve heading + aria-labelledby; role=list/listitem rows
- Remove fabricated 1ms floor: sub-ms yields 0, UI shows '<1 ms'
- Strict latency types: reject null/bool/str/float/negative/Infinity/huge
  (frontend + backend); no coercion or clipping
- Failed upstream-attempt duration never overwrites prior successful latency;
  stale-but-measured feeds labeled 'last known' truthfully
- Notifications fetch starts immediately (auth-independent), concurrent with
  shared current_user auth; deterministic concurrency proof
- Repair tests: real DOM transitions (browser-verified), production failure
  shape, panel-hidden assertion, malformed-value matrix
This commit is contained in:
timmy committed 2026-08-22 23:22:40 +00:00
1 parent 398598e154
commit 81d288405f
4 files changed
+512 -160

No files matched your search

+35 -11
View File
@@ -15,8 +15,14 @@
}
function boundedLatencyMs(value) {
const ms = Number(value);
return Number.isFinite(ms) && ms >= 0 ? Math.min(Math.round(ms), 3600000) : null;
// Strict acceptance only: actual finite nonnegative bounded integers.
// Rejects null, booleans, strings, arrays, floats, fractions, negatives,
// Infinity, and huge values. No Number() coercion, no clipping.
if (typeof value !== 'number') return null;
if (!Number.isFinite(value)) return null;
if (!Number.isInteger(value)) return null;
if (value < 0 || value > 3600000) return null;
return value;
}
const latencyBuckets = [
@@ -67,12 +73,24 @@
function formatLatency(ms) {
if (ms === null) return 'not measured';
if (ms === 0) return '<1 ms';
if (ms >= 10000) return Math.round(ms / 1000) + ' s';
if (ms >= 1000) return (ms / 1000).toFixed(1) + ' s';
return ms + ' ms';
}
function renderBucketLatency(description, panel) {
// Render rows *inside* the existing #bucket-latency-rows container so the
// panel heading and its aria-labelledby target are never replaced. Each
// generated row carries role=listitem so the list semantics hold.
const rowsContainer = (typeof panel.querySelector === 'function')
? (panel.querySelector('#bucket-latency-rows') || panel)
: panel;
if (rowsContainer !== panel) {
rowsContainer.innerHTML = '';
} else {
panel.innerHTML = '';
}
const rows = description.feeds.map(feed => ({
key: feed.key,
label: feed.label,
@@ -81,20 +99,26 @@
}));
if (!rows.some(row => row.latencyMs !== null)) {
panel.hidden = true;
panel.innerHTML = '';
return rows;
}
panel.hidden = false;
panel.innerHTML = rows.map(row => {
for (const row of rows) {
const slow = row.latencyMs !== null && row.latencyMs >= 2000 ? ' slow' : '';
const value = formatLatency(row.latencyMs);
// A delayed feed shows the last measurement that succeeded, so say so.
const suffix = row.stale && row.latencyMs !== null ? ' <span class="small muted">last known</span>' : '';
return '<div class="bucket-latency-row" data-bucket="' + row.key + '">' +
'<strong>' + row.label + '</strong>' +
'<span class="bucket-latency-value' + slow + '">' + value + suffix + '</span>' +
'</div>';
}).join('');
// A stale feed shows the last measurement that succeeded, so say so.
const suffix = row.stale && row.latencyMs !== null
? ' <span class="small muted">last known</span>' : '';
const html = '<div class="bucket-latency-row' + slow + '" role="listitem" data-bucket="' +
row.key + '"><strong>' + row.label + '</strong>' +
'<span class="bucket-latency-value' + slow + '">' + value + suffix + '</span></div>';
if (typeof document !== 'undefined') {
const wrapper = document.createElement('div');
wrapper.innerHTML = html;
rowsContainer.appendChild(wrapper.firstChild);
} else {
rowsContainer.appendChild({outerHTML: html});
}
}
return rows;
}