Skip to content

Commit 6bb61c3

Browse files
committed
feat(deno): include all orchestrion integrations
Automatically pull in all orchestrion integrations defined in server-utils into the Deno SDK. Move the `setAsyncLocalStorageAsyncContextStrategy()` into the Deno SDK init method, since it's eventually called by any client that uses even the default set of integrations anyway. Consume the list of integrations from @sentry/server-utils, so that any new integrations that are added will automatically get picked up by the Deno SDK, without having another piece to keep in sync and remember to add. The existing wrapped-and-renamed integrations are deprecated, but still on by default, warning that their names will change in v11. As this will be a breaking change, it's not added here, but a `todo` note is added to remind us to make it a plain alias in the next major. Closes #21225 Closes JS-2634
1 parent 83659e1 commit 6bb61c3

16 files changed

Lines changed: 204 additions & 175 deletions

File tree

dev-packages/deno-integration-tests/suites/orchestrion-mysql/test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ Deno.test('@sentry/deno/import: transforms mysql so it publishes the orchestrion
9595
assert(line.includes('"runtime":["mysql"]'), `expected runtime marker, got: ${line}`);
9696
});
9797

98-
// Exercises the SDK path end-to-end: `init()` wires `denoMysqlIntegration`
99-
// (which installs the AsyncLocalStorage context strategy and subscribes to the
98+
// Exercises the SDK path end-to-end: `init()` installs the AsyncLocalStorage
99+
// context strategy and wires `denoMysqlIntegration` (which subscribes to the
100100
// channel), and we drive the `orchestrion:mysql:query` channel manually — the
101101
// same events the orchestrion transform publishes around `connection.query()` —
102102
// so no live database is needed. Asserting a nested `db` span proves the

dev-packages/deno-integration-tests/suites/orchestrion-postgres/test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ Deno.test('@sentry/deno/import: transforms pg so it publishes the orchestrion ch
9595
assert(line.includes('"runtime":["pg","pg-pool"]'), `expected runtime marker, got: ${line}`);
9696
});
9797

98-
// Exercises the SDK path end-to-end: `init()` wires `denoPostgresIntegration`
99-
// (which installs the AsyncLocalStorage context strategy and subscribes to the
98+
// Exercises the SDK path end-to-end: `init()` installs the AsyncLocalStorage
99+
// context strategy and wires `denoPostgresIntegration` (which subscribes to the
100100
// channel), and we drive the `orchestrion:pg:query` channel manually — the
101101
// same events the orchestrion transform publishes around `client.query()` —
102102
// so no live database is needed. Asserting a nested `db` span proves the

packages/deno/src/index.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,14 +111,24 @@ export { denoHttpIntegration } from './integrations/http';
111111
export type { DenoHttpIntegrationOptions } from './integrations/http';
112112
export { denoRedisIntegration } from './integrations/redis';
113113
export type { DenoRedisIntegrationOptions } from './integrations/redis';
114+
// Deprecated: these default integrations are renamed (`Deno*` → the shared name) in the next major;
115+
// re-exported until then. See each integration's `@deprecated` note.
116+
/* eslint-disable typescript/no-deprecated */
114117
export { denoMysqlIntegration } from './integrations/mysql';
115118
export { denoPostgresIntegration } from './integrations/postgres';
116119
export { denoAmqplibIntegration } from './integrations/amqplib';
117-
export { denoDataloaderIntegration } from './integrations/dataloader';
118-
export { denoKnexIntegration } from './integrations/knex';
119120
export { denoKoaIntegration } from './integrations/koa';
120121
export { denoMongoIntegration } from './integrations/mongo';
121122
export { denoMongooseIntegration } from './integrations/mongoose';
123+
/* eslint-enable typescript/no-deprecated */
124+
export { dataloaderChannelIntegration, knexChannelIntegration } from '@sentry/server-utils/orchestrion';
125+
// The deprecated `denoDataloaderIntegration`/`denoKnexIntegration` wrappers are
126+
// superseded by the universal integrations re-exported above, but kept for
127+
// back-compat.
128+
/* eslint-disable typescript/no-deprecated */
129+
export { denoDataloaderIntegration } from './integrations/dataloader';
130+
export { denoKnexIntegration } from './integrations/knex';
131+
/* eslint-enable typescript/no-deprecated */
122132
export { denoContextIntegration } from './integrations/context';
123133
export { globalHandlersIntegration } from './integrations/globalhandlers';
124134
export { normalizePathsIntegration } from './integrations/normalizepaths';

packages/deno/src/integrations/amqplib.ts

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,26 @@
11
import { amqplibChannelIntegration } from '@sentry/server-utils/orchestrion';
22
import type { Integration, IntegrationFn } from '@sentry/core';
33
import { defineIntegration, extendIntegration } from '@sentry/core';
4-
import { setAsyncLocalStorageAsyncContextStrategy } from '../async';
54

65
const INTEGRATION_NAME = 'DenoAmqplib' as const;
76

8-
/**
9-
* Create spans for `amqplib` publish/consume operations under Deno.
10-
*
11-
* `amqplib` channels are injected by the orchestrion runtime hook at load time.
12-
* The `@sentry/deno/import` loader must be active for this integration to
13-
* record anything.
14-
*
15-
* The channel-subscription logic is shared with the other server runtimes in
16-
* `@sentry/server-utils`. This just installs Deno's `AsyncLocalStorage` context
17-
* strategy (so spans nest under the active span and survive amqplib's internal
18-
* callback dispatch) before delegating.
19-
*/
207
const _denoAmqplibIntegration = (() => {
21-
const inner = amqplibChannelIntegration();
22-
23-
return extendIntegration(inner, {
8+
return extendIntegration(amqplibChannelIntegration(), {
249
name: INTEGRATION_NAME,
25-
setupOnce() {
26-
setAsyncLocalStorageAsyncContextStrategy();
27-
},
2810
});
2911
}) satisfies IntegrationFn;
3012

13+
// TODO(v11): turn wrapping into plain alias
14+
/**
15+
* Create spans for `amqplib` publish/consume operations under Deno.
16+
* Included in the default integrations.
17+
*
18+
* @deprecated In the next major this wrapper is removed and `amqplib` is
19+
* instrumented by the shared `amqplibChannelIntegration` directly, so the
20+
* default integration's name changes from `DenoAmqplib` to `Amqplib`.
21+
* If you reference it by name (e.g. to disable it), update `'DenoAmqplib'` to
22+
* `'Amqplib'`.
23+
*/
3124
export const denoAmqplibIntegration = defineIntegration(_denoAmqplibIntegration) as () => Integration & {
3225
name: 'DenoAmqplib';
3326
setupOnce: () => void;

packages/deno/src/integrations/dataloader.ts

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,22 @@
11
import { dataloaderChannelIntegration } from '@sentry/server-utils/orchestrion';
22
import type { Integration, IntegrationFn } from '@sentry/core';
33
import { defineIntegration, extendIntegration } from '@sentry/core';
4-
import { setAsyncLocalStorageAsyncContextStrategy } from '../async';
54

65
const INTEGRATION_NAME = 'DenoDataloader' as const;
76

8-
/**
9-
* Create spans for `dataloader` load/batch operations under Deno.
10-
*
11-
* `dataloader` channels are injected by the orchestrion runtime hook at load time.
12-
* The `@sentry/deno/import` loader must be active for this integration to
13-
* record anything.
14-
*
15-
* The channel-subscription logic is shared with the other server runtimes in
16-
* `@sentry/server-utils`. This just installs Deno's `AsyncLocalStorage` context
17-
* strategy (so spans nest under the active span and survive dataloader's deferred
18-
* batch dispatch) before delegating.
19-
*/
207
const _denoDataloaderIntegration = (() => {
21-
const inner = dataloaderChannelIntegration();
22-
23-
return extendIntegration(inner, {
8+
return extendIntegration(dataloaderChannelIntegration(), {
249
name: INTEGRATION_NAME,
25-
setupOnce() {
26-
setAsyncLocalStorageAsyncContextStrategy();
27-
},
2810
});
2911
}) satisfies IntegrationFn;
3012

13+
/**
14+
* Create spans for `dataloader` load/batch operations under Deno.
15+
*
16+
* @deprecated `dataloaderChannelIntegration` is now available directly, so this
17+
* wrapper is redundant and will be removed in a future major. Use it (or the
18+
* shared `dataloaderChannelIntegration`) instead.
19+
*/
3120
export const denoDataloaderIntegration = defineIntegration(_denoDataloaderIntegration) as () => Integration & {
3221
name: 'DenoDataloader';
3322
setupOnce: () => void;

packages/deno/src/integrations/deno-serve.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import type { IntegrationFn } from '@sentry/core';
22
import { debug, defineIntegration } from '@sentry/core';
3-
import { setAsyncLocalStorageAsyncContextStrategy } from '../async';
43
import type { RequestHandlerWrapperOptions } from '../wrap-deno-request-handler';
54
import { wrapDenoRequestHandler } from '../wrap-deno-request-handler';
65

@@ -63,8 +62,6 @@ const _denoServeIntegration = (() => {
6362
return {
6463
name: INTEGRATION_NAME,
6564
setupOnce() {
66-
setAsyncLocalStorageAsyncContextStrategy();
67-
6865
const originalServe = Deno.serve;
6966
const wrappedServe = instrumentedDenoServe(originalServe);
7067

packages/deno/src/integrations/http.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
HTTP_ON_CLIENT_REQUEST,
1212
HTTP_ON_SERVER_REQUEST,
1313
} from '@sentry/core';
14-
import { setAsyncLocalStorageAsyncContextStrategy } from '../async';
1514
import {
1615
DENO_VERSION,
1716
HTTP_CLIENT_DIAGNOSTICS_CHANNEL_SUPPORTED,
@@ -111,11 +110,6 @@ const _denoHttpIntegration = ((options: DenoHttpIntegrationOptions = {}) => {
111110
return;
112111
}
113112

114-
// Wire up Deno's AsyncLocalStorage-backed ACS so the server subscription's
115-
// `withIsolationScope(clone, ...)` actually activates the cloned scope.
116-
// Without this, request isolation and span creation degrade silently.
117-
setAsyncLocalStorageAsyncContextStrategy();
118-
119113
if (HTTP_SERVER_DIAGNOSTICS_CHANNEL_SUPPORTED) {
120114
const { [HTTP_ON_SERVER_REQUEST]: onHttpServerRequest } = getHttpServerSubscriptions({
121115
// `spans` falls through to the client's tracing config when unset.

packages/deno/src/integrations/knex.ts

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,22 @@
11
import { knexChannelIntegration } from '@sentry/server-utils/orchestrion';
22
import type { Integration, IntegrationFn } from '@sentry/core';
33
import { defineIntegration, extendIntegration } from '@sentry/core';
4-
import { setAsyncLocalStorageAsyncContextStrategy } from '../async';
54

65
const INTEGRATION_NAME = 'DenoKnex' as const;
76

8-
/**
9-
* Create spans for `knex` queries under Deno.
10-
*
11-
* `knex` channels are injected by the orchestrion runtime hook at load time.
12-
* The `@sentry/deno/import` loader must be active for this integration to
13-
* record anything.
14-
*
15-
* The channel-subscription logic is shared with the other server runtimes in
16-
* `@sentry/server-utils`. This just installs Deno's
17-
* `AsyncLocalStorage` context strategy (so spans nest under the active
18-
* span and survive knex's internal callback dispatch) before delegating.
19-
*/
207
const _denoKnexIntegration = (() => {
21-
const inner = knexChannelIntegration();
22-
23-
return extendIntegration(inner, {
8+
return extendIntegration(knexChannelIntegration(), {
249
name: INTEGRATION_NAME,
25-
setupOnce() {
26-
setAsyncLocalStorageAsyncContextStrategy();
27-
},
2810
});
2911
}) satisfies IntegrationFn;
3012

13+
/**
14+
* Create spans for `knex` queries under Deno.
15+
*
16+
* @deprecated `knexChannelIntegration` is now available directly, so this
17+
* wrapper is redundant and will be removed in a future major. Use
18+
* `knexChannelIntegration` instead.
19+
*/
3120
export const denoKnexIntegration = defineIntegration(_denoKnexIntegration) as () => Integration & {
3221
name: 'DenoKnex';
3322
setupOnce: () => void;

packages/deno/src/integrations/koa.ts

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,26 @@ import { koaChannelIntegration } from '@sentry/server-utils/orchestrion';
22
import type { KoaChannelIntegrationOptions } from '@sentry/server-utils/orchestrion';
33
import type { Integration, IntegrationFn } from '@sentry/core';
44
import { defineIntegration, extendIntegration } from '@sentry/core';
5-
import { setAsyncLocalStorageAsyncContextStrategy } from '../async';
65

76
const INTEGRATION_NAME = 'DenoKoa' as const;
87

9-
/**
10-
* Create spans for `koa` middleware/router layers under Deno. Requires the
11-
* `@sentry/deno/import` loader. Delegates to the shared subscriber in
12-
* `@sentry/server-utils`, adding Deno's `AsyncLocalStorage` context strategy so
13-
* spans nest under the active HTTP server span.
14-
*/
158
const _denoKoaIntegration = ((options: KoaChannelIntegrationOptions = {}) => {
16-
const inner = koaChannelIntegration(options);
17-
18-
return extendIntegration(inner, {
9+
return extendIntegration(koaChannelIntegration(options), {
1910
name: INTEGRATION_NAME,
20-
setupOnce() {
21-
setAsyncLocalStorageAsyncContextStrategy();
22-
},
2311
});
2412
}) satisfies IntegrationFn;
2513

14+
// TODO(v11): turn wrapping into plain alias
15+
/**
16+
* Create spans for `koa` middleware/router layers under Deno.
17+
* Included in the default integrations.
18+
*
19+
* @deprecated In the next major this wrapper is removed and `koa` is
20+
* instrumented by the shared `koaChannelIntegration` directly, so the
21+
* default integration's name changes from `DenoKoa` to `Koa`.
22+
* If you reference it by name (e.g. to disable it), update `'DenoKoa'` to
23+
* `'Koa'`.
24+
*/
2625
export const denoKoaIntegration = defineIntegration(_denoKoaIntegration) as (
2726
options?: KoaChannelIntegrationOptions,
2827
) => Integration & {

packages/deno/src/integrations/mongo.ts

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,26 @@
11
import { mongodbChannelIntegration } from '@sentry/server-utils/orchestrion';
22
import type { Integration, IntegrationFn } from '@sentry/core';
33
import { defineIntegration, extendIntegration } from '@sentry/core';
4-
import { setAsyncLocalStorageAsyncContextStrategy } from '../async';
54

65
const INTEGRATION_NAME = 'DenoMongo' as const;
76

8-
/**
9-
* Create spans for `mongodb` queries under Deno.
10-
*
11-
* `mongodb` channels are injected by the orchestrion runtime hook at load time.
12-
* The `@sentry/deno/import` loader must be active for this integration to
13-
* record anything.
14-
*
15-
* The channel-subscription logic is shared with the other server runtimes in
16-
* `@sentry/server-utils`. This just installs Deno's
17-
* `AsyncLocalStorage` context strategy (so spans nest under the active
18-
* span and survive mongodb's internal callback dispatch) before delegating.
19-
*/
207
const _denoMongoIntegration = (() => {
21-
const inner = mongodbChannelIntegration();
22-
23-
return extendIntegration(inner, {
8+
return extendIntegration(mongodbChannelIntegration(), {
249
name: INTEGRATION_NAME,
25-
setupOnce() {
26-
setAsyncLocalStorageAsyncContextStrategy();
27-
},
2810
});
2911
}) satisfies IntegrationFn;
3012

13+
// TODO(v11): turn wrapping into plain alias
14+
/**
15+
* Create spans for `mongodb` queries under Deno.
16+
* Included in the default integrations.
17+
*
18+
* @deprecated In the next major this wrapper is removed and `mongodb` is
19+
* instrumented by the shared `mongodbChannelIntegration` directly, so the
20+
* default integration's name changes from `DenoMongo` to `Mongo`.
21+
* If you reference it by name (e.g. to disable it), update `'DenoMongo'` to
22+
* `'Mongo'`.
23+
*/
3124
export const denoMongoIntegration = defineIntegration(_denoMongoIntegration) as () => Integration & {
3225
name: 'DenoMongo';
3326
setupOnce: () => void;

0 commit comments

Comments
 (0)