Skip to content

Commit 596608d

Browse files
committed
feat(cloudflare): Only attach Orchestrion integrations when needed
1 parent c63885b commit 596608d

3 files changed

Lines changed: 33 additions & 9 deletions

File tree

packages/cloudflare/src/sdk.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,22 @@ import {
1414
import type { CloudflareClientOptions, CloudflareOptions } from './client';
1515
import { CloudflareClient } from './client';
1616
import { makeFlushLock } from './flush';
17-
import { channelIntegrations, isOrchestrionInjected } from '@sentry/server-utils/orchestrion';
1817
import { httpServerIntegration } from './integrations/httpServer';
1918
import { fetchIntegration } from './integrations/fetch';
2019
import { honoIntegration } from './integrations/hono';
2120
import { setupOpenTelemetryTracer } from './opentelemetry/tracer';
2221
import { makeCloudflareTransport } from './transport';
2322
import { defaultStackParser } from './vendor/stacktrace';
2423

24+
/**
25+
* Exact copy of the function from `@sentry/server-utils/orchestrion`.
26+
* This is to avoid importing the orchestrion package directly into the cloudflare package.
27+
* TODO(v11): Use `@sentry/server-utils/orchestrion` once we move to `nodejs_compat` by default
28+
*/
29+
function getRegisteredChannelIntegrations(): Integration[] {
30+
return (globalThis.__SENTRY_ORCHESTRION__?.integrations || []).map(factory => factory());
31+
}
32+
2533
/** Get the default integrations for the Cloudflare SDK. */
2634
export function getDefaultIntegrations(options: CloudflareOptions): Integration[] {
2735
// TODO(v11): Drop this transitional gating and let `requestDataIntegration` rely on the resolved
@@ -47,9 +55,11 @@ export function getDefaultIntegrations(options: CloudflareOptions): Integration[
4755
consoleIntegration(),
4856
// The orchestrion diagnostics-channel subscribers (mysql, pg, …). The
4957
// `@sentry/cloudflare/vite` plugin injects the channels at build time and
50-
// sets the orchestrion bundler marker; without it the channels never fire,
51-
// so only add the subscribers when injection actually happened.
52-
...(isOrchestrionInjected() ? Object.values(channelIntegrations).map(factory => factory()) : []),
58+
// adds a generated registration module to the bundle, which puts the
59+
// subscriber factories on the global marker. Read from there instead of
60+
// importing them so bundles built without the plugin — where the channels
61+
// would never fire — don't ship the code.
62+
...getRegisteredChannelIntegrations(),
5363
];
5464
}
5565

packages/cloudflare/src/vite/index.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ import { sentryOrchestrionPlugin } from '@sentry/server-utils/orchestrion/vite';
1212
* (e.g. `mysql`) at build time via orchestrion, so the SDK can trace them
1313
* without monkey-patching, which wouldn't work in workerd anyway.
1414
*
15-
* The Cloudflare SDK detects the injection at runtime and subscribes to the
16-
* channels automatically; the worker itself only needs the usual
15+
* It also injects a generated registration module into the bundle, which
16+
* registers the matching channel-subscriber integrations for `Sentry.init` to
17+
* pick up. The SDK itself doesn't import them, so workers built without this
18+
* plugin don't ship that code; the worker only needs the usual
1719
* `Sentry.withSentry` wrapping.
1820
*
1921
* @example
@@ -46,5 +48,5 @@ import { sentryOrchestrionPlugin } from '@sentry/server-utils/orchestrion/vite';
4648
* ```
4749
*/
4850
export function sentryCloudflareVitePlugin() {
49-
return sentryOrchestrionPlugin();
51+
return sentryOrchestrionPlugin({ registerIntegrations: true });
5052
}

packages/cloudflare/test/sdk.test.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ describe('getDefaultIntegrations', () => {
6666
delete globalThis.__SENTRY_ORCHESTRION__;
6767
});
6868

69-
test('does not add orchestrion channel integrations when injection did not happen', () => {
69+
test('does not add orchestrion channel integrations when none were registered', () => {
7070
delete globalThis.__SENTRY_ORCHESTRION__;
7171

7272
const names = getDefaultIntegrations({}).map(i => i.name);
@@ -76,11 +76,23 @@ describe('getDefaultIntegrations', () => {
7676
expect(names).not.toContain('LruMemoizer');
7777
});
7878

79-
test('adds orchestrion channel integrations when the bundler marker is set', () => {
79+
test('does not add orchestrion channel integrations when only the bundler marker is set', () => {
8080
globalThis.__SENTRY_ORCHESTRION__ = { bundler: true };
8181

8282
const names = getDefaultIntegrations({}).map(i => i.name);
8383

84+
expect(names).not.toContain('Mysql');
85+
expect(names).not.toContain('Postgres');
86+
expect(names).not.toContain('LruMemoizer');
87+
});
88+
89+
test('adds orchestrion channel integrations registered by the injected registration module', async () => {
90+
// Mirror what the module the vite plugin injects into bundles does at runtime.
91+
const { registerChannelIntegrations } = await import('@sentry/server-utils/orchestrion');
92+
registerChannelIntegrations();
93+
94+
const names = getDefaultIntegrations({}).map(i => i.name);
95+
8496
expect(names).toContain('Mysql');
8597
expect(names).toContain('Postgres');
8698
expect(names).toContain('LruMemoizer');

0 commit comments

Comments
 (0)