Conversation
size-limit report 📦
|
7b5f046 to
1e9f2bd
Compare
1e9f2bd to
45aed9a
Compare
2b018b4 to
5af594d
Compare
0541fb0 to
68fb5f5
Compare
68fb5f5 to
dcfe28e
Compare
dcfe28e to
43202bf
Compare
Deno's synchronous module loader (`Module.registerHooks`) reports
`format: undefined` for the modules we instrument, so tracing-hooks treated
them as CommonJS and injected `require()` into ESM (`require is not defined`).
Infer the module format from the source for instrumented targets when the
runtime leaves it unset (no-op on Node, which always sets `format`).
The hono-4 e2e app also constructed its sub-apps at module eval before
`Sentry.init()` ran, so `honoIntegration` subscribed to the constructor channel
too late to instrument them (their internal `.request()` calls produced no
span). Move init into a dedicated `instrument.{bun,deno}.ts` imported first,
matching the Node `--import` ordering.
Finally, define the shared middleware as anonymous function expressions: a named
expression whose name equals its binding gets renamed by Bun's bundler
(`middlewareA` -> `middlewareA2`), which leaked into the middleware span name.
deno variant is un-skipped; cloudflare stays skipped pending a workerd-safe
instrumentation path (diagnostics_channel publish/runStores are disallowed at
module scope on workerd).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RaYGdTstWVZKU9X4NjtYV1
…are) Exposes `honoMiddleware(app)` from `@sentry/node`, `@sentry/bun`, `@sentry/deno` and `@sentry/cloudflare`: it applies the same Hono span patches and returns the same request/response middleware the automatic `honoIntegration` uses, but as a manual, config- and init-free API (`app.use(honoMiddleware(app))`). Sentry must still be initialized separately. This is the supported path on Cloudflare Workers, where automatic constructor-channel instrumentation cannot run: the app is built at module scope, and on workerd `diagnostics_channel`'s `hasSubscribers` is a method (always truthy) rather than a boolean getter, so the transform's "no subscribers" fast-path never triggers and its publish/`runStores` calls execute at module scope — which workerd forbids, crashing the worker at boot. Accordingly: - the Cloudflare vite plugin now excludes `hono` from the orchestrion transform (new `excludeModules` option), so `new Hono()` stays untransformed and the worker boots; users instrument via `honoMiddleware` instead; - the Cloudflare-only eager constructor-channel arm is removed from `honoIntegration` (it relied on the same disallowed module-scope publishing). Node/Bun/Deno keep the automatic constructor-channel instrumentation unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RaYGdTstWVZKU9X4NjtYV1
…eno format workaround
`@apm-js-collab/tracing-hooks` 0.13.1 fixes the runtime hook to infer a module's
type from its source when the host loader leaves `format` unset (its new
`unlabeledModuleType`). That is exactly what our register.ts workaround did for
Deno's synchronous loader, which reported `format: undefined` and caused
`ReferenceError: require is not defined` when a CJS wrapper was injected into an
ES module.
With the fix upstream, remove `loadWithInferredFormat`/`isInstrumentedTarget`
and register the plain `{ resolve, load }` hooks again. (code-transformer and
code-transformer-bundler-plugins are already at their latest, 0.18.1 / 0.7.4.)
Verified: the hono-4 Deno e2e no longer crashes and instruments correctly. The
one remaining Deno failure (`http.request.header.*` as a string vs array) is an
unrelated pre-existing issue from the header-array change (#24231) not yet
covering Deno's `winterCGHeadersToDict` path; fixed on develop.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RaYGdTstWVZKU9X4NjtYV1
…le-cloud-serverless These SDKs already re-export the server-side integration surface (incl. `honoIntegration`); add `honoMiddleware` alongside so users of those SDKs can manually instrument a Hono app where automatic constructor-channel instrumentation can't run. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RaYGdTstWVZKU9X4NjtYV1
Bun runs on JavaScriptCore, which rejects orchestrion's default constructor instrumentation for DERIVED classes (e.g. `class Hono extends HonoBase`): it reads `this` in a `finally` that does not lexically enclose the nested `super()` call, and JSC statically rejects that with ReferenceError: 'super()' must be called in derived constructor before accessing |this| ...crashing `new Hono()` at boot. V8 (Node/Deno/workerd) accepts it via a runtime this-binding check. Add a `traceSync` override, wired into the Bun bundler plugin only, that runs the built-in transform and then—for derived constructors only—relocates the `__apm$ctx.self ??= this` capture out of the `finally` into `__apm$traced` (after `__apm$wrapped(...)` returns, a scope that encloses `super()`). Every other node is left byte-identical, and only Bun (JSC) gets the override, so cloudflare/vite, esbuild/webpack and the Node/Deno runtime keep the default output. Guarded: if the transformer's generated shape changes, it no-ops and warns rather than silently reintroducing the crash. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RaYGdTstWVZKU9X4NjtYV1
43202bf to
b4a5995
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit b823241. Configure here.
| return /^https?:\/\//.test(input) ? new URL(input).pathname : input; | ||
| // `app.request()` accepts absolute URLs as well as relative paths. Parse both | ||
| // against a dummy base so the query string is stripped from the span name. | ||
| return new URL(input, 'http://sentry-internal').pathname; |
There was a problem hiding this comment.
Pathname parse can abort requests
Low Severity
extractPathname now runs every string through new URL against a dummy base, including relative Hono paths. That constructor throws on some inputs Hono accepts (such as // or http:), and the Proxy calls it before Reflect.apply, so instrumentation can abort app.request. Protocol-relative strings are also parsed as absolute URLs, so the span name can drop the host segment Hono actually requests.
Additional Locations (1)
Triggered by project rule: PR Review Guidelines for Cursor Bot
Reviewed by Cursor Bugbot for commit b823241. Configure here.


Summary
Moves the Hono instrumentation into
@sentry/server-utilsand drives it through orchestrion, so Hono is auto-instrumented out of the box by@sentry/node,@sentry/bun,@sentry/deno, and@sentry/cloudflare— no@sentry/honoimport and no manualsentry()middleware required.@sentry/honokeeps working exactly as before: it now re-uses the shared code from@sentry/server-utilsinstead of owning its own copy.How it works
@sentry/hono/src/sharedto@sentry/server-utils/src/integrations/hono.honoIntegration(default in the server SDKs'getErrorIntegrations()) hooks theHonoconstructor via an orchestrion diagnostics channel (orchestrion:hono:honoConstructor) and, on every new app, registers the Sentry request/response middleware first and applies the span patches.@sentry/server-utilstakes no dependency onhono— not at runtime (theHonoprototype is derived from the live app instance; matched routes are read from the request's own getters instead ofhono/route) and not at build/type time (the needed types are vendored inhonoTypes.ts).Per-runtime enablement
honoIntegrationis added by default everywhere. We had to add a little hack to ensure it is called early enough in cloudflare, we can remove this once Cloudflare capture crashes / data before we export the default fetch handler #24375 is fixed.Duplicate handling
Request handling is deduplicated per request via the isolation scope, so all of these run the Sentry logic exactly once:
sentry()middleware alongside the auto-instrumentation,app.request()dispatches (a new Hono context, same isolation scope).A user-provided
shouldHandleErrorstill wins even when its middleware is deduplicated behind the auto-instrumentation.Tests
@sentry/server-utils):isMiddleware,defaultShouldHandleError, and the dedup logic increateHonoMiddleware.suites/hono): auto-instrumentation with plain@sentry/node(ESM + CJS) — transaction naming, error capture/mechanism, plus regression cases for mounted sub-apps (no stray<anonymous>middleware span) and internal.request()(no span rename / request-data pollution).http.serverspan (method/route/url) for Mastra's Hono-served agent endpoint.hono-4app exercising node/bun/deno/cloudflare via the runtime SDKs directly; the previous@sentry/hono-based app is preserved ashono-4-legacy.skipsupport (getTestMatrix.mjs+run.ts).Known limitations / follow-ups
Module.registerHookspath,@apm-js-collab/tracing-hooksderives the module type only fromresult.format, which Deno doesn't report as'module'for Hono's ESM build — so a CJSrequire()is injected into an ES module (ReferenceError: require is not defined). Filed as Sync hooks path injects CommonJS require() into ESM modules on Deno → ReferenceError: require is not defined apm-js-collab/tracing-hooks#53. Thehono-4deno variant is markedskipuntil it lands. (Node works because it uses the asyncModule.registerpath, which reports the format correctly.)@sentry/honoremains as-is (thin re-export layer); no deprecation for now.