Skip to content

feat(server-utils): Migrate FirebaseInstrumentation to orchestrion#22141

Merged
nicohrubec merged 8 commits into
developfrom
feat/firebase-orchestrion
Jul 21, 2026
Merged

feat(server-utils): Migrate FirebaseInstrumentation to orchestrion#22141
nicohrubec merged 8 commits into
developfrom
feat/firebase-orchestrion

Conversation

@mydea

@mydea mydea commented Jul 9, 2026

Copy link
Copy Markdown
Member

Rewrites the Firebase integration off InstrumentationBase to an orchestrion diagnostics-channel listener in @sentry/server-utils, following the mysql (#20900) and graphql (#21885) migrations. The channel-based integration reuses the OTel Firebase name, so opting in via experimentalUseDiagnosticsChannelInjection() swaps it in 1:1 for the OTel one (which stays the default).

Firestore — subscribes to orchestrion:@firebase/firestore:{add,get,set,delete}-doc (injected into firestore's lite addDoc/getDocs/setDoc/deleteDoc) and emits the same db.query client spans via bindTracingChannelToSpan, with a distinct auto.firebase.orchestrion.firestore origin.

firebase-functions — the onX(...) provider functions register a handler and return synchronously, so the span can't be bound to the registration call. Instead the channel start subscriber rewraps the handler argument (orchestrion forwards the mutated args array to the real call), so the returned cloud function opens a SERVER span + error boundary on invocation, with auto.firebase.orchestrion.functions origin.

The node-firebase e2e firestore suite additionally runs with E2E_ORCHESTRION=true to assert the orchestrion origin.

Closes #20919

@mydea

mydea commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

This depends on nodejs/orchestrion-js#90 being released (and subsequently released in tracing-hooks etc), as we need to target hashed files:

- firebase-functions → orchestrion works ✅ (the onRequest channel fires — onRequest is declared in the stable lib/v2/providers/https.js).
- firestore → blocked ❌. This is the cause of the "0 spans" e2e failure.

Root cause of the e2e failure

@firebase/firestore@4.16.0 (what firebase@12 installs) is built with Rollup code-splitting: addDoc/getDocs/setDoc/deleteDoc are declared in a content-hash-named shared chunk —
dist/lite/common-460c749a.node.cjs.js — and index.node.cjs.js only re-exports them (exports.addDoc = common….addDoc).

Orchestrion transforms the declaration site, so it must target the chunk file. But:
- My config targets index.node.cjs.js (which has no function addDoc) → never transformed → channel never fires → 0 spans.
- The chunk name (common-460c749a) is a content hash that changes every firestore version, and @apm-js-collab/code-transformer (v?) matches filePath exactly — no glob/regex (I tested *,
**, etc.). So there's no stable, version-independent path to target.

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

Path Size % Change Change
@sentry/browser 27.75 kB - -
@sentry/browser - with treeshaking flags 26.18 kB - -
@sentry/browser (incl. Tracing) 46.56 kB - -
@sentry/browser (incl. Tracing + Span Streaming) 48.37 kB - -
@sentry/browser (incl. Tracing, Profiling) 51.36 kB - -
@sentry/browser (incl. Tracing, Replay) 85.84 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 75.46 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 90.55 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 103.21 kB - -
@sentry/browser (incl. Feedback) 44.93 kB - -
@sentry/browser (incl. sendFeedback) 32.55 kB - -
@sentry/browser (incl. FeedbackAsync) 37.69 kB - -
@sentry/browser (incl. Metrics) 28.83 kB - -
@sentry/browser (incl. Logs) 29.05 kB - -
@sentry/browser (incl. Metrics & Logs) 29.76 kB - -
@sentry/react 29.54 kB - -
@sentry/react (incl. Tracing) 48.84 kB - -
@sentry/vue 33.17 kB - -
@sentry/vue (incl. Tracing) 48.52 kB - -
@sentry/svelte 27.78 kB - -
CDN Bundle 30.14 kB - -
CDN Bundle (incl. Tracing) 48.53 kB - -
CDN Bundle (incl. Logs, Metrics) 31.73 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 49.83 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) 70.99 kB - -
CDN Bundle (incl. Tracing, Replay) 86.05 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 87.35 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 91.85 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 93.12 kB - -
CDN Bundle - uncompressed 89.88 kB - -
CDN Bundle (incl. Tracing) - uncompressed 146.73 kB - -
CDN Bundle (incl. Logs, Metrics) - uncompressed 94.59 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 150.71 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 219.35 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 265.96 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 269.93 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 279.67 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 283.62 kB - -
@sentry/nextjs (client) 51.36 kB - -
@sentry/sveltekit (client) 46.99 kB - -
@sentry/core/server 80.26 kB - -
@sentry/core/browser 66.69 kB - -
@sentry/node-core 63.21 kB - -
@sentry/node 125.76 kB - -
@sentry/node (incl. diagnostics channel injection) 151.2 kB +0.94% +1.39 kB 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection) 70.03 kB - -
@sentry/node/light 51.32 kB - -
@sentry/node - without tracing 74.92 kB - -
@sentry/aws-serverless 84.15 kB - -
@sentry/cloudflare (withSentry) - minified 197.66 kB - -
@sentry/cloudflare (withSentry) 486.61 kB - -

View base workflow run

@mydea
mydea force-pushed the feat/firebase-orchestrion branch from 8aabf34 to 24d1c33 Compare July 13, 2026 09:58
@mydea
mydea force-pushed the feat/firebase-orchestrion branch from 24d1c33 to 19a4eeb Compare July 15, 2026 07:53
@mydea
mydea force-pushed the feat/firebase-orchestrion branch from 19a4eeb to 99dca08 Compare July 15, 2026 10:57
@mydea
mydea changed the base branch from develop to fn/bump-orchestrion-latest July 15, 2026 10:57
Base automatically changed from fn/bump-orchestrion-latest to develop July 15, 2026 14:04
mydea added a commit that referenced this pull request Jul 15, 2026
This bumps orchestrion dependencies:

* `"@apm-js-collab/code-transformer-bundler-plugins": "^0.6.0"`
* `"@apm-js-collab/tracing-hooks": "^0.12.0"`

which basically just updates those to use
`"@apm-js-collab/code-transformer": "^0.18.0"` as deps.


Required for #22141
@mydea
mydea force-pushed the feat/firebase-orchestrion branch from 538303f to 6c63b54 Compare July 15, 2026 14:04
Comment thread packages/server-utils/src/orchestrion/config/firebase.ts Outdated
@mydea
mydea force-pushed the feat/firebase-orchestrion branch 2 times, most recently from 6cbf56b to 785badf Compare July 17, 2026 08:01
@nicohrubec
nicohrubec force-pushed the feat/firebase-orchestrion branch from 2caa029 to ffea8e1 Compare July 21, 2026 07:31

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit b0358a6. Configure here.

@nicohrubec
nicohrubec marked this pull request as ready for review July 21, 2026 08:13
@nicohrubec
nicohrubec requested review from a team as code owners July 21, 2026 08:13
@nicohrubec
nicohrubec requested review from andreiborza, chargome and nicohrubec and removed request for a team and nicohrubec July 21, 2026 08:13
Comment thread packages/server-utils/test/orchestrion/firebase.test.ts Outdated
@nicohrubec
nicohrubec force-pushed the feat/firebase-orchestrion branch from b0358a6 to 4aeccc2 Compare July 21, 2026 08:43
Comment thread packages/nextjs/src/config/turbopack/constructTurbopackConfig.ts

@chargome chargome left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just the tests and some convention follow ups!


describe('firebaseChannelIntegration', () => {
beforeAll(() => {
installTestAsyncContextStrategy();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove tests that depend on this and move to integration tests

@nicohrubec
nicohrubec requested a review from andreiborza July 21, 2026 09:08
mydea and others added 8 commits July 21, 2026 12:58
Adds an orchestrion diagnostics-channel `Firebase` integration in
`@sentry/server-utils`, replacing the `InstrumentationBase` approach when
`experimentalUseDiagnosticsChannelInjection()` is enabled (swapping in 1:1 for
the OTel `Firebase` integration by name).

- Firestore: subscribes to `orchestrion:@firebase/firestore:{add,get,set,delete}-doc`
  and emits the same `db.query` spans via `bindTracingChannelToSpan`, with a
  distinct `auto.firebase.orchestrion.firestore` origin.
- firebase-functions: subscribes to `orchestrion:firebase-functions:*` and
  rewraps the handler argument of each `onX(...)` registration in the channel's
  `start` so the returned cloud function opens a SERVER span + error boundary on
  invocation, with `auto.firebase.orchestrion.functions` origin.

Closes #20919

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
firebase >=12.8 (firestore >=4.10) moved addDoc/getDocs/setDoc/deleteDoc
into a hash-named shared chunk, so orchestrion's exact-path filePath match
no longer hit them and no firestore spans were emitted. Use a RegExp
filePath matching both the old `index.node.*` and new `common-<hash>.node.*`
chunks. Also align the functions span op assertion with `function.firebase`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… disable

Remove the unused `DocumentData` type, the unread `FirestoreSettings.ssl`
and `FirestoreLike.settings` members, and narrow the `toJSON` return to what
`buildAttributes` actually reads. Switching the `FirebaseOptions` index
signature to `unknown` lets the file drop its `no-explicit-any` eslint-disable.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`getPortAndAddress` is a line-for-line port of the OTel firestore parser but
its 9-case unit suite wasn't ported alongside it. Bring the IPv4/IPv6/host
edge cases over, plus a missing-`host` case the guard clause handles.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Turbopack requires loader options to be JSON-serializable, so a RegExp
`module.filePath` (used by the firestore config) was silently dropped and no
firestore channels were injected under Turbopack — while webpack, which passes
the config in-process, worked. Encode via `serializeInstrumentations` at the
Turbopack boundary; the loader revives the RegExp on the other side.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… tests

Drop the SDK-setup harness (installTestAsyncContextStrategy + setupOnce +
tracingChannel round-trip) and call the exported functions directly. Tests
that only existed to exercise the channel wiring are removed: the deleteDoc
error lifecycle is generic bind behavior already covered in
tracing-channel.test.ts, and the missing-reference / parent-selection cases
live in the instrumentFirebase closure (covered by the orchestrion e2e).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@nicohrubec
nicohrubec force-pushed the feat/firebase-orchestrion branch from 275c399 to f5e200b Compare July 21, 2026 10:59
@nicohrubec
nicohrubec merged commit 4d8cdbd into develop Jul 21, 2026
226 checks passed
@nicohrubec
nicohrubec deleted the feat/firebase-orchestrion branch July 21, 2026 11:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rewrite FirebaseInstrumentation to orchestrion

4 participants