Tracing Blade views (and the anonymous-component fix)
Adding a view.render span collector to the tracing SDK so Blade templates show up as traced operations — plus the 1.2.1 and 1.3.0 fixes it took to get right.
Three SDK releases in one day — lookout/tracing 1.2.0, 1.2.1, and 1.3.0 — all chasing one feature: the Views watcher.
The idea
A request trace already shows controllers, queries, cache, and HTTP calls. What was missing: where the rendering time goes. Blade templates can be a surprising chunk of a slow request — a deeply nested partial, an N+1 hiding inside a @foreach that lazy-loads a relation per row. So I added a view.render span collector: every Blade view becomes a traced operation with its name and duration.
Why it took three releases
Shipping a collector is easy. Shipping a correct one is three releases:
- 1.2.0 — the collector itself, hooking Laravel's view events to open/close a
view.renderspan per template. - 1.2.1 —
Fix view collector registration. The collector wasn't registering reliably depending on boot order. Instrumentation that only sometimes runs is worse than none — it makes the data lie. Fixed the registration so it's deterministic. - 1.3.0 —
Record anonymous Blade components in view collector. Anonymous components (`<section class="@container flex flex-col p-3 sm:p-6 bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 rounded-xl shadow-sm ring-1 ring-gray-900/5 default:col-span-full default:lg:col-span-6 default:row-span-1" x-data="{ loading: false, init() { } }"
` with no class) don't fire the same events as regular views, so they were invisible — exactly the lightweight, heavily-reused components you'd want to see. 1.3.0 catches them too.
The lesson
Instrumentation has a brutal correctness bar. A dashboard widget can be slightly wrong and you shrug. But if your tracing is wrong — missing spans, double-counting, registering half the time — it actively misleads you during the one moment you're relying on it: an incident. "Mostly works" isn't a passing grade for a collector.
That's why each fix shipped as its own release with its own version bump. The release tracking I'd just added made that painless.
Next session: an operator admin panel so I can actually support the people using this.