declarative relay deployment on hetzner relay-eval.waow.tech
atproto relay
14
fork

Configure Feed

Select the types of activity you want to include in your feed.

relay-eval: exclude event-count outliers from coverage union

when a relay reports >1.3x the median event count (likely replaying
after a restart), exclude it from the effective union used to compute
coverage percentages. prevents a single replaying relay from dragging
all other relays' coverage scores down.

applies to both the dashboard snapshot view and the OG SVG image.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

zzstoatzz 822a179f 77a7c881

+75 -29
+47 -9
relay-eval/src/server.zig
··· 148 148 allocator.free(stats); 149 149 } 150 150 151 - const diffs = try store.getRunDiffs(allocator, run_id); 151 + const diff_counts = try store.getDiffCounts(allocator, run_id); 152 + defer { 153 + for (diff_counts) |dc| { 154 + allocator.free(dc.relay); 155 + allocator.free(dc.classification); 156 + } 157 + allocator.free(diff_counts); 158 + } 159 + 160 + const diff_samples = try store.getDiffSamples(allocator, run_id, 30); 152 161 defer { 153 - for (diffs) |d| { 162 + for (diff_samples) |d| { 154 163 allocator.free(d.relay); 155 164 allocator.free(d.did); 156 165 allocator.free(d.classification); 157 166 } 158 - allocator.free(diffs); 167 + allocator.free(diff_samples); 159 168 } 160 169 161 170 var json: std.ArrayList(u8) = .empty; ··· 170 179 s.host, s.events, s.unique_dids, s.connected, 171 180 }); 172 181 } 173 - try json.appendSlice(allocator, "],\"diffs\":["); 174 - for (diffs, 0..) |d, i| { 182 + try json.appendSlice(allocator, "],\"diff_counts\":["); 183 + for (diff_counts, 0..) |dc, i| { 184 + if (i > 0) try json.appendSlice(allocator, ","); 185 + try json.print(allocator, "{{\"relay\":\"{s}\",\"classification\":\"{s}\",\"count\":{d}}}", .{ 186 + dc.relay, dc.classification, dc.count, 187 + }); 188 + } 189 + try json.appendSlice(allocator, "],\"diff_samples\":["); 190 + for (diff_samples, 0..) |d, i| { 175 191 if (i > 0) try json.appendSlice(allocator, ","); 176 192 try json.print(allocator, "{{\"relay\":\"{s}\",\"did\":\"{s}\",\"classification\":\"{s}\"}}", .{ 177 193 d.relay, d.did, d.classification, ··· 260 276 ); 261 277 262 278 const max_rows: usize = @min(stats.len, 10); 263 - const union_dids: u64 = @intCast(@max(run_meta.union_dids, 1)); 279 + 280 + // outlier detection: if a relay has >1.5x median events, it's likely replaying; 281 + // use the max unique_dids among non-outliers as the effective union 282 + var events_sorted: [32]u64 = undefined; 283 + const n_events = @min(stats.len, 32); 284 + for (stats[0..n_events], 0..) |s, idx| events_sorted[idx] = s.events; 285 + std.mem.sort(u64, events_sorted[0..n_events], {}, std.sort.asc(u64)); 286 + const median_events = if (n_events > 0) events_sorted[n_events / 2] else 0; 287 + const threshold = median_events + median_events * 3 / 10; // 1.3x 288 + 289 + var effective_union: u64 = @intCast(@max(run_meta.union_dids, 1)); 290 + if (median_events > 0) { 291 + var max_non_outlier: u64 = 1; 292 + var has_outlier = false; 293 + for (stats) |s| { 294 + if (s.events > threshold) { 295 + has_outlier = true; 296 + } else if (s.events > 0 and s.unique_dids > max_non_outlier) { 297 + max_non_outlier = s.unique_dids; 298 + } 299 + } 300 + if (has_outlier) effective_union = max_non_outlier; 301 + } 264 302 265 303 for (stats[0..max_rows], 0..) |s, i| { 266 304 const y: u32 = 130 + @as(u32, @intCast(i)) * 42; 267 - const pct_x10: u64 = @as(u64, s.unique_dids) * 1000 / union_dids; 305 + const pct_x10: u64 = @as(u64, s.unique_dids) * 1000 / effective_union; 268 306 const pct_int: u32 = @intCast(pct_x10 / 10); 269 307 const pct_frac: u32 = @intCast(pct_x10 % 10); 270 - const bar_w: u32 = @intCast(@min(@as(u64, s.unique_dids) * 600 / union_dids, 600)); 308 + const bar_w: u32 = @intCast(@min(@as(u64, s.unique_dids) * 600 / effective_union, 600)); 271 309 272 310 const color: []const u8 = if (pct_x10 >= 990) "#3fb950" else if (pct_x10 >= 950) "#58a6ff" else if (pct_x10 >= 800) "#bc8cff" else "#8b949e"; 273 311 ··· 281 319 // footer 282 320 const window_min: i32 = @divTrunc(run_meta.window_seconds, 60); 283 321 try svg.appendSlice(allocator, "<text x=\"60\" y=\"590\" fill=\"#8b949e\" font-family=\"monospace\" font-size=\"14\">"); 284 - try appendFormattedInt(&svg, allocator, run_meta.union_dids); 322 + try appendFormattedInt(&svg, allocator, @intCast(effective_union)); 285 323 try svg.print(allocator, " active accounts &#xb7; {d} minute window</text></svg>", .{window_min}); 286 324 287 325 try sendResponse(stream, "200 OK", "image/svg+xml", svg.items);
+28 -20
relay-eval/src/static/index.html
··· 684 684 const union = data.union_dids || 0; 685 685 let h = ''; 686 686 687 + // outlier detection — relays with >1.5x median events are likely replaying 688 + const actv = data.stats.filter(s => s.events > 0).map(s => s.events).sort((a, b) => a - b); 689 + const median = actv.length > 0 ? actv[Math.floor(actv.length / 2)] : 0; 690 + const outliers = new Set(); 691 + if (median > 0) { 692 + for (const s of data.stats) { 693 + if (s.events > median * 1.3) outliers.add(s.host); 694 + } 695 + } 696 + 697 + // recompute union excluding outliers so replaying relays don't drag others down 698 + const effectiveUnion = outliers.size > 0 699 + ? Math.max(...data.stats.filter(s => !outliers.has(s.host) && s.events > 0).map(s => s.unique_dids), 1) 700 + : union; 701 + 687 702 // summary 688 703 h += `<div class="summary">`; 689 704 h += `<span class="summary-item">measured ${tip(ago(data.timestamp), utc(data.timestamp))}</span>`; 690 705 h += `<span class="summary-sep"> \u00b7 </span>`; 691 706 h += `<span class="summary-item">${tip(winLabel(data.window_seconds), data.window_seconds + 's collection window')} window</span>`; 692 707 h += `<span class="summary-sep"> \u00b7 </span>`; 693 - h += `<span class="summary-item"><span class="stat">${union.toLocaleString()}</span> active accounts</span>`; 708 + h += `<span class="summary-item"><span class="stat">${effectiveUnion.toLocaleString()}</span> active accounts</span>`; 694 709 h += `</div>`; 695 710 696 711 // operator legend ··· 705 720 } 706 721 h += `</div>`; 707 722 708 - // diffs by relay 723 + // diffs by relay (aggregated counts + sample DIDs) 709 724 const rd = {}; 710 - for (const d of data.diffs) { 725 + for (const c of (data.diff_counts || [])) { 726 + if (!rd[c.relay]) rd[c.relay] = { coverage_gap: 0, unresolvable: 0, deactivated: 0, dids: [] }; 727 + rd[c.relay][c.classification] = c.count; 728 + } 729 + for (const d of (data.diff_samples || [])) { 711 730 if (!rd[d.relay]) rd[d.relay] = { coverage_gap: 0, unresolvable: 0, deactivated: 0, dids: [] }; 712 - rd[d.relay][d.classification]++; 713 731 rd[d.relay].dids.push(d); 714 - } 715 - 716 - // outlier detection 717 - const actv = data.stats.filter(s => s.events > 0).map(s => s.events).sort((a, b) => a - b); 718 - const median = actv.length > 0 ? actv[Math.floor(actv.length / 2)] : 0; 719 - const outliers = new Set(); 720 - if (median > 0) { 721 - for (const s of data.stats) { 722 - if (s.events > median * 1.5) outliers.add(s.host); 723 - } 724 732 } 725 733 726 734 // coverage table with tabs ··· 758 766 h += `<td class="run-by hm">${byLink}</td>`; 759 767 h += `<td class="num">${s.events.toLocaleString()}${isOutlier ? `<span class="outlier" title="${pctAbove}% above median \u2014 likely replaying backlog after a restart">\u26a0</span>` : ''}</td>`; 760 768 h += `<td class="num">${s.unique_dids.toLocaleString()}</td>`; 761 - h += `<td class="num">${pct(s.unique_dids, union)}</td>`; 769 + h += `<td class="num">${pct(s.unique_dids, effectiveUnion)}</td>`; 762 770 h += `<td class="num">${missed > 0 ? missed.toLocaleString() : '\u2014'}</td>`; 763 - h += `<td class="hm">${bar(s.unique_dids, union)}</td>`; 771 + h += `<td class="hm">${bar(s.unique_dids, effectiveUnion)}</td>`; 764 772 h += `</tr>`; 765 773 } 766 774 h += `</tbody></table></div>`; ··· 768 776 769 777 if (outliers.size > 0) { 770 778 const names = [...outliers].map(host => rn(host)).join(', '); 771 - h += `<p class="outlier-note">\u26a0 ${names} reported significantly more events than other relays during this window \u2014 likely replaying buffered events after a restart.</p>`; 779 + h += `<p class="outlier-note">\u26a0 ${names} reported significantly more events than other relays during this window \u2014 likely replaying buffered events after a restart. coverage percentages are computed against the non-outlier union to avoid skewing results.</p>`; 772 780 } 773 781 774 782 // breakdown ··· 810 818 h += `</tr></tbody>`; 811 819 812 820 h += `<tbody class="xbody" id="xb-${id}">`; 813 - for (const x of d.dids.slice(0, 30)) { 821 + for (const x of d.dids) { 814 822 const cls = x.classification === 'coverage_gap' ? 'c-gap' : x.classification === 'unresolvable' ? 'c-unr' : 'c-dead'; 815 823 const label = x.classification === 'coverage_gap' ? 'active' : x.classification; 816 824 h += `<tr class="drow"><td>${did(x.did)}</td><td colspan="4" class="${cls}">${label}</td></tr>`; 817 825 } 818 - if (d.dids.length > 30) { 819 - h += `<tr class="drow"><td colspan="5">\u2026 and ${d.dids.length - 30} more</td></tr>`; 826 + if (total > d.dids.length) { 827 + h += `<tr class="drow"><td colspan="5">\u2026 and ${total - d.dids.length} more</td></tr>`; 820 828 } 821 829 h += `</tbody>`; 822 830 }