Times every matched Phoenix route, kind: "controller". Call once at startup, e.g.
application.ex's own start/2, before the rest of the supervision tree starts:
ForgeOpsTracker.Integrations.Phoenix.attach()Attaches to [:phoenix, :router_dispatch, :stop] (confirmed directly against the installed
phoenix source, not assumed from docs: Phoenix.Router.__call__/5 emits this around every
matched route's own plug pipeline, controller action included), a global event name, not
per-endpoint-namespaced, so this one call covers every Phoenix endpoint in the host app. An
unmatched route (a 404) never fires this event at all, the same "only a real match gets timed"
behavior every other language's own controller/action instrumentation in this repo already has.
transaction_name is "<HTTP method> <route pattern>" (e.g. "GET /users/:id"), not the
literal path: metadata.route is Phoenix's own matched route pattern, which keeps a distinct
user id from exploding into its own separate transaction the way the literal path would.
Also records the same automatic "controller" breadcrumb every other client's own request/
controller-lifecycle instrumentation already does (message "METHOD route", level "error" on
a 5xx response and "info" otherwise, data holding the status and path), gated independently on
track_breadcrumbs the same way ForgeOpsTracker.record_performance/3 is already independently
gated on track_performance: this one telemetry event is where several genuinely independent
mechanisms happen to be recorded from, not one mechanism triggering another.
Also opens a trace at [:phoenix, :router_dispatch, :start] and finishes it at :stop (or
:exception), the root span named like the transaction above, so a slow request's own breakdown
reaches /spans (see ForgeOpsTracker.span/4). ForgeOpsTracker.Integrations.Ecto adds a
"database" span per query into it. Outbound HTTP is not instrumented (each HTTP client library
has its own telemetry events): wrap a call in ForgeOpsTracker.span/4.