docs(html): update §06 + §08 with verified layer-by-layer instrumentation usage
After the user pushed back on intent-vs-shipped state, I greped each layer and updated both explainers to reflect actual code, not documented intent. data-flow-explainer.html §06 — "Tracing & error capture": - New "Where instrumentation actually lives" table — per-layer breakdown of inline span / inline capture / composed-via-wrapper, with a verifiable grep showing only repos have inline calls. - New "The wrapper sandwich" code block showing the actual repo body shape next to the bind-time withSpan(withCapture(...)) composition. - Capture-rules table refined to reflect the R44 fix that just landed: use cases capture business-rule errors and output-schema failures (not bubbled-from-repo); controllers capture safeParse failures (not bubbled-from-use-case); the __sentryReported flag is what makes this safe. - Double-report-guard paragraph now mentions withCapture, SentryLogger, and RecordingLogger all check the flag (not just SentryLogger). di-explainer.html §08 — "Instrumentation symbols": - Wiring path updated from "withSpan(tracer, ...)" to "withSpan(withCapture(...))" to reflect the post-merge wiring. - New "Two wrappers, applied as a sandwich" table comparing what each wrapper does and where it fires; closing note that repos can't use the wrapper because they own per-call attributes. Also bundled: a 1-line aesthetic SVG noise tweak in di-explainer.html (opacity='0.25', baseFrequency 0.85→0.95) that was sitting in the working tree before this session — preserved across the Plan 10 merge via stash/pop and now committed alongside the doc update. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -50,7 +50,7 @@ body {
|
||||
body::before {
|
||||
content: "";
|
||||
position: fixed; inset: 0;
|
||||
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'><filter id='n'><feTurbulence baseFrequency='0.85' numOctaves='3'/><feColorMatrix values='0 0 0 0 0.10 0 0 0 0 0.07 0 0 0 0 0.05 0 0 0 0 0.10 0'/></filter><rect width='200' height='200' filter='url(%23n)'/></svg>");
|
||||
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200' opacity='0.25'><filter id='n'><feTurbulence baseFrequency='0.95' numOctaves='3'/><feColorMatrix values='0 0 0 0 0.10 0 0 0 0 0.07 0 0 0 0 0.05 0 0 0 0 0.10 0'/></filter><rect width='200' height='200' filter='url(%23n)'/></svg>");
|
||||
pointer-events: none;
|
||||
opacity: 0.45;
|
||||
mix-blend-mode: multiply;
|
||||
@@ -1185,11 +1185,32 @@ footer .colophon {
|
||||
└─ Noop or Sentry binders ← bind to sharedContainer
|
||||
└─ bindProductionX(config, tracer, logger)
|
||||
└─ feature container also binds TRACER + LOGGER
|
||||
└─ withSpan(tracer, ...) at every use case + controller</code></pre>
|
||||
└─ withSpan(withCapture(...)) at every use case + controller</code></pre>
|
||||
|
||||
<p class="trace-p"><strong>Why per-feature containers also get the binding:</strong> repository classes resolve TRACER/LOGGER through the container; controllers and use cases receive instrumentation via the bind-time wrapper instead.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="trace-h3" style="margin-top: 36px;">Two wrappers, applied as a sandwich</h3>
|
||||
<p class="trace-p"><code>withSpan</code> and <code>withCapture</code> are higher-order functions that take a <code>(args) => Promise<R></code> and return the same shape. The binders compose them: <code>withSpan(withCapture(factory(deps)))</code>. Span is outermost so an errored span's timing reflects the capture-and-rethrow.</p>
|
||||
<table class="capture-rules">
|
||||
<thead>
|
||||
<tr><th>Wrapper</th><th>What it does</th><th>Where it fires</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>withSpan(tracer, opts, fn)</code></td>
|
||||
<td>Calls <code>tracer.startSpan(opts, () => fn(...))</code>. Pure delegation — no error handling of its own; status-on-error logic lives in the tracer impl.</td>
|
||||
<td>Around every use case + controller, at DI bind time</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>withCapture(logger, tags, fn)</code></td>
|
||||
<td>On throw: checks <code>__sentryReported</code>; if not set, calls <code>logger.captureException(err, { tags })</code>, marks the flag, re-throws. If already set, just re-throws.</td>
|
||||
<td>Around every use case + controller, inside the span wrapper</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="trace-p">Repositories are different — they call <code>this.tracer.startSpan</code> + <code>this.logger.captureException</code> inline per method, because they own the per-call attributes (count, IDs, slugs) that the wrapper has no way to know.</p>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
|
||||
Reference in New Issue
Block a user