.nornir/assets/metrics-flow.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 860 400" font-family="ui-sans-serif,system-ui,sans-serif" font-size="13">
<defs>
<marker id="arw" markerWidth="9" markerHeight="9" refX="7" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L7,3 L0,6 Z" fill="#64748b"/>
</marker>
<style>
.box{fill:#0f172a;stroke:#334155;stroke-width:1.5}
.lbl{fill:#e2e8f0}
.sub{fill:#94a3b8;font-size:11px}
.engine{fill:#1e293b;stroke:#38bdf8;stroke-width:2}
.hit{fill:#065f46;stroke:#10b981}
.surface{fill:#312e81;stroke:#818cf8}
.edge{stroke:#64748b;stroke-width:1.5;fill:none}
@media (prefers-color-scheme: light){
.box{fill:#f1f5f9;stroke:#cbd5e1}
.lbl{fill:#0f172a}.sub{fill:#475569}
.engine{fill:#e0f2fe;stroke:#0284c7}
.hit{fill:#d1fae5;stroke:#059669}
.surface{fill:#e0e7ff;stroke:#4f46e5}
}
</style>
</defs>
<text x="20" y="26" class="lbl" font-size="15" font-weight="700">Prometheus /metrics — bump at the call sites, render on scrape</text>
<!-- The bump sites -->
<rect class="surface" x="20" y="56" width="200" height="42" rx="8"/>
<text x="120" y="76" class="lbl" text-anchor="middle">HTTP door: get/put/delete</text>
<text x="120" y="91" class="sub" text-anchor="middle">record_request(verb, status, bytes)</text>
<rect class="surface" x="20" y="112" width="200" height="42" rx="8"/>
<text x="120" y="132" class="lbl" text-anchor="middle">/-/search · /-/sbom doors</text>
<text x="120" y="147" class="sub" text-anchor="middle">record_request(Search|Sbom, …)</text>
<rect class="surface" x="20" y="168" width="200" height="42" rx="8"/>
<text x="120" y="188" class="lbl" text-anchor="middle">retention executor</text>
<text x="120" y="203" class="sub" text-anchor="middle">record_retention_run()</text>
<!-- The global registry -->
<rect class="engine" x="290" y="96" width="190" height="118" rx="8"/>
<text x="385" y="122" class="lbl" text-anchor="middle" font-weight="700">metrics::global()</text>
<text x="385" y="142" class="sub" text-anchor="middle">OnceLock<Metrics></text>
<text x="385" y="159" class="sub" text-anchor="middle">AtomicU64 counters:</text>
<text x="385" y="175" class="sub" text-anchor="middle">requests{verb} · bytes</text>
<text x="385" y="191" class="sub" text-anchor="middle">errors · retention_runs</text>
<text x="385" y="207" class="sub" text-anchor="middle">(lock-free, relaxed)</text>
<path class="edge" d="M220,77 C255,90 255,120 290,128" marker-end="url(#arw)"/>
<path class="edge" d="M220,133 L290,145" marker-end="url(#arw)"/>
<path class="edge" d="M220,189 C255,176 255,180 290,172" marker-end="url(#arw)"/>
<!-- The scrape door -->
<rect class="box" x="530" y="96" width="180" height="118" rx="8"/>
<text x="620" y="122" class="lbl" text-anchor="middle" font-weight="700">GET /metrics</text>
<text x="620" y="142" class="sub" text-anchor="middle">render_prometheus(</text>
<text x="620" y="158" class="sub" text-anchor="middle">repo_counts)</text>
<text x="620" y="178" class="sub" text-anchor="middle">snapshot atomics +</text>
<text x="620" y="194" class="sub" text-anchor="middle">list() each backend</text>
<text x="620" y="210" class="sub" text-anchor="middle">(spawn_blocking)</text>
<path class="edge" d="M480,155 L530,155" marker-end="url(#arw)"/>
<!-- Backends for the gauge -->
<rect class="box" x="530" y="248" width="180" height="52" rx="8"/>
<text x="620" y="270" class="lbl" text-anchor="middle">every configured backend</text>
<text x="620" y="288" class="sub" text-anchor="middle">list() → artifact count</text>
<path class="edge" d="M620,214 L620,248" marker-end="url(#arw)"/>
<path class="edge" d="M620,248 L620,216" marker-end="url(#arw)"/>
<!-- Output -->
<rect class="hit" x="740" y="96" width="100" height="118" rx="8"/>
<text x="790" y="122" class="lbl" text-anchor="middle" font-weight="700">text 0.0.4</text>
<text x="790" y="146" class="sub" text-anchor="middle">counters</text>
<text x="790" y="164" class="sub" text-anchor="middle">+ gauges</text>
<text x="790" y="188" class="sub" text-anchor="middle">Prometheus</text>
<text x="790" y="204" class="sub" text-anchor="middle">scrapes it</text>
<path class="edge" d="M710,155 L740,155" marker-end="url(#arw)"/>
<text x="20" y="352" class="sub">Read-only, unauthenticated, unaudited — exposes only aggregate counters, never artifact bytes. No hot-path cost beyond a relaxed atomic add.</text>
<text x="20" y="374" class="sub">The per-repo artifact gauge is the one scrape-time I/O (bounded list, off the reactor); an errored backend reports 0, never sinks the scrape.</text>
</svg>