Skip to content

Commit bad4f1e

Browse files
committed
feat(core): Add client.getIntegrationByName()
And also deprecate both `getIntegration()` as well as `getIntegrationById()` which is only on the baseclient, but not on the client type, anyhow :grimace:. Usage: ```ts const replay = getClient().getIntegrationByName('Replay'); ``` Or, if you want to have an easier time with types: ```ts const replay = getClient().getIntegrationByName<Replay>('Replay'); ```
1 parent 6faec42 commit bad4f1e

File tree

26 files changed

+97
-67
lines changed

26 files changed

+97
-67
lines changed

MIGRATION.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@ npx @sentry/migr8@latest
88

99
This will let you select which updates to run, and automatically update your code. Make sure to still review all code changes!
1010

11+
## Deprecate `getIntegration()` and `getIntegrationById()`
12+
13+
This deprecates `getIntegration()` on both the hub & the client, as well as `getIntegrationById()` on the baseclient.
14+
Instead, use `getIntegrationByName()`.
15+
You can optionally pass an integration generic to make it easier to work with typescript:
16+
17+
```ts
18+
const replay = getClient().getIntegrationByName<Replay>('Replay');
19+
```
20+
1121
## Deprecate `scope.getSpan()` and `scope.setSpan()`
1222

1323
Instead, you can get the currently active span via `Sentry.getActiveSpan()`.

dev-packages/browser-integration-tests/loader-suites/loader/onLoad/customBrowserTracing/test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ sentryTest('should handle custom added BrowserTracing integration', async ({ get
2727
expect(eventData.transaction_info?.source).toEqual('url');
2828

2929
const tracePropagationTargets = await page.evaluate(() => {
30-
const browserTracing = (window as any).Sentry.getCurrentHub().getClient().getIntegrationById('BrowserTracing');
30+
const browserTracing = (window as any).Sentry.getCurrentHub().getClient().getIntegrationByName('BrowserTracing');
3131
return browserTracing.options.tracePropagationTargets;
3232
});
3333

dev-packages/browser-integration-tests/loader-suites/loader/onLoad/customIntegrations/test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ sentryTest('should handle custom added integrations & default integrations', asy
2424
});
2525

2626
const hasCustomIntegration = await page.evaluate(() => {
27-
return !!(window as any).Sentry.getCurrentHub().getClient().getIntegrationById('CustomIntegration');
27+
return !!(window as any).Sentry.getCurrentHub().getClient().getIntegrationByName('CustomIntegration');
2828
});
2929

3030
const hasReplay = await page.evaluate(() => {
31-
return !!(window as any).Sentry.getCurrentHub().getClient().getIntegrationById('Replay');
31+
return !!(window as any).Sentry.getCurrentHub().getClient().getIntegrationByName('Replay');
3232
});
3333
const hasBrowserTracing = await page.evaluate(() => {
34-
return !!(window as any).Sentry.getCurrentHub().getClient().getIntegrationById('BrowserTracing');
34+
return !!(window as any).Sentry.getCurrentHub().getClient().getIntegrationByName('BrowserTracing');
3535
});
3636

3737
expect(hasCustomIntegration).toEqual(true);

dev-packages/browser-integration-tests/loader-suites/loader/onLoad/customIntegrationsFunction/test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ sentryTest(
2121
});
2222

2323
const hasCustomIntegration = await page.evaluate(() => {
24-
return !!(window as any).Sentry.getCurrentHub().getClient().getIntegrationById('CustomIntegration');
24+
return !!(window as any).Sentry.getCurrentHub().getClient().getIntegrationByName('CustomIntegration');
2525
});
2626

2727
const hasReplay = await page.evaluate(() => {
28-
return !!(window as any).Sentry.getCurrentHub().getClient().getIntegrationById('Replay');
28+
return !!(window as any).Sentry.getCurrentHub().getClient().getIntegrationByName('Replay');
2929
});
3030
const hasBrowserTracing = await page.evaluate(() => {
31-
return !!(window as any).Sentry.getCurrentHub().getClient().getIntegrationById('BrowserTracing');
31+
return !!(window as any).Sentry.getCurrentHub().getClient().getIntegrationByName('BrowserTracing');
3232
});
3333

3434
expect(hasCustomIntegration).toEqual(true);

dev-packages/browser-integration-tests/loader-suites/loader/onLoad/customReplay/test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ sentryTest('should handle custom added Replay integration', async ({ getLocalTes
2727
expect(eventData.segment_id).toBe(0);
2828

2929
const useCompression = await page.evaluate(() => {
30-
const replay = (window as any).Sentry.getCurrentHub().getClient().getIntegrationById('Replay');
30+
const replay = (window as any).Sentry.getCurrentHub().getClient().getIntegrationByName('Replay');
3131
return replay._replay.getOptions().useCompression;
3232
});
3333

packages/astro/test/client/sdk.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ describe('Sentry client SDK', () => {
6060
});
6161

6262
const integrationsToInit = browserInit.mock.calls[0][0]?.integrations;
63-
const browserTracing = getClient<BrowserClient>()?.getIntegrationById('BrowserTracing');
63+
const browserTracing = getClient<BrowserClient>()?.getIntegrationByName('BrowserTracing');
6464

6565
expect(integrationsToInit).toContainEqual(expect.objectContaining({ name: 'BrowserTracing' }));
6666
expect(browserTracing).toBeDefined();
@@ -76,7 +76,7 @@ describe('Sentry client SDK', () => {
7676
});
7777

7878
const integrationsToInit = browserInit.mock.calls[0][0]?.integrations;
79-
const browserTracing = getClient<BrowserClient>()?.getIntegrationById('BrowserTracing');
79+
const browserTracing = getClient<BrowserClient>()?.getIntegrationByName('BrowserTracing');
8080

8181
expect(integrationsToInit).not.toContainEqual(expect.objectContaining({ name: 'BrowserTracing' }));
8282
expect(browserTracing).toBeUndefined();
@@ -91,7 +91,7 @@ describe('Sentry client SDK', () => {
9191
});
9292

9393
const integrationsToInit = browserInit.mock.calls[0][0]?.integrations;
94-
const browserTracing = getClient<BrowserClient>()?.getIntegrationById('BrowserTracing');
94+
const browserTracing = getClient<BrowserClient>()?.getIntegrationByName('BrowserTracing');
9595

9696
expect(integrationsToInit).not.toContainEqual(expect.objectContaining({ name: 'BrowserTracing' }));
9797
expect(browserTracing).toBeUndefined();
@@ -108,7 +108,7 @@ describe('Sentry client SDK', () => {
108108

109109
const integrationsToInit = browserInit.mock.calls[0][0]?.integrations;
110110

111-
const browserTracing = getClient<BrowserClient>()?.getIntegrationById('BrowserTracing') as BrowserTracing;
111+
const browserTracing = getClient<BrowserClient>()?.getIntegrationByName('BrowserTracing') as BrowserTracing;
112112
const options = browserTracing.options;
113113

114114
expect(integrationsToInit).toContainEqual(expect.objectContaining({ name: 'BrowserTracing' }));

packages/core/src/baseclient.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,13 +327,24 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
327327
* Gets an installed integration by its `id`.
328328
*
329329
* @returns The installed integration or `undefined` if no integration with that `id` was installed.
330+
* @deprecated Use `getIntegrationByName()` instead.
330331
*/
331332
public getIntegrationById(integrationId: string): Integration | undefined {
332-
return this._integrations[integrationId];
333+
return this.getIntegrationByName(integrationId);
333334
}
334335

335336
/**
336-
* @inheritDoc
337+
* Gets an installed integration by its name.
338+
*
339+
* @returns The installed integration or `undefined` if no integration with that `name` was installed.
340+
*/
341+
public getIntegrationByName<T extends Integration = Integration>(integrationName: string): T | undefined {
342+
return this._integrations[integrationName] as T | undefined;
343+
}
344+
345+
/**
346+
* Returns the client's instance of the given integration class, it any.
347+
* @deprecated Use `getIntegrationByName()` instead.
337348
*/
338349
public getIntegration<T extends Integration>(integration: IntegrationClass<T>): T | null {
339350
try {

packages/core/src/hub.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,11 +421,14 @@ export class Hub implements HubInterface {
421421

422422
/**
423423
* @inheritDoc
424+
*
425+
* @deprecated Use `Sentry.getClient().getIntegrationByName()` instead.
424426
*/
425427
public getIntegration<T extends Integration>(integration: IntegrationClass<T>): T | null {
426428
const client = this.getClient();
427429
if (!client) return null;
428430
try {
431+
// eslint-disable-next-line deprecation/deprecation
429432
return client.getIntegration(integration);
430433
} catch (_oO) {
431434
DEBUG_BUILD && logger.warn(`Cannot retrieve integration ${integration.id} from the current Hub`);

packages/core/test/lib/base.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,7 +1485,7 @@ describe('BaseClient', () => {
14851485
client.setupIntegrations();
14861486

14871487
expect(Object.keys((client as any)._integrations).length).toEqual(1);
1488-
expect(client.getIntegration(TestIntegration)).toBeTruthy();
1488+
expect(client.getIntegrationByName(TestIntegration.id)).toBeTruthy();
14891489
});
14901490

14911491
test('skips installation if DSN is not provided', () => {
@@ -1496,7 +1496,7 @@ describe('BaseClient', () => {
14961496
client.setupIntegrations();
14971497

14981498
expect(Object.keys((client as any)._integrations).length).toEqual(0);
1499-
expect(client.getIntegration(TestIntegration)).toBeFalsy();
1499+
expect(client.getIntegrationByName(TestIntegration.id)).toBeFalsy();
15001500
});
15011501

15021502
test('skips installation if `enabled` is set to `false`', () => {
@@ -1511,7 +1511,7 @@ describe('BaseClient', () => {
15111511
client.setupIntegrations();
15121512

15131513
expect(Object.keys((client as any)._integrations).length).toEqual(0);
1514-
expect(client.getIntegration(TestIntegration)).toBeFalsy();
1514+
expect(client.getIntegrationByName(TestIntegration.id)).toBeFalsy();
15151515
});
15161516

15171517
test('skips installation if integrations are already installed', () => {
@@ -1526,7 +1526,7 @@ describe('BaseClient', () => {
15261526
client.setupIntegrations();
15271527

15281528
expect(Object.keys((client as any)._integrations).length).toEqual(1);
1529-
expect(client.getIntegration(TestIntegration)).toBeTruthy();
1529+
expect(client.getIntegrationByName(TestIntegration.id)).toBeTruthy();
15301530
expect(setupIntegrationsHelper).toHaveBeenCalledTimes(1);
15311531

15321532
// ...but it shouldn't try to install a second time

packages/core/test/mocks/integration.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Event, EventProcessor, Integration } from '@sentry/types';
22

3-
import { getCurrentHub, getCurrentScope } from '../../src';
3+
import { getClient, getCurrentScope } from '../../src';
44

55
export class TestIntegration implements Integration {
66
public static id: string = 'TestIntegration';
@@ -9,7 +9,7 @@ export class TestIntegration implements Integration {
99

1010
public setupOnce(): void {
1111
const eventProcessor: EventProcessor = (event: Event) => {
12-
if (!getCurrentHub().getIntegration(TestIntegration)) {
12+
if (!getClient()?.getIntegrationByName?.('TestIntegration')) {
1313
return event;
1414
}
1515

packages/ember/addon/instance-initializers/sentry-performance.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,8 +441,8 @@ export async function instrumentForPerformance(appInstance: ApplicationInstance)
441441

442442
if (
443443
client &&
444-
(client as BrowserClient).getIntegrationById &&
445-
(client as BrowserClient).getIntegrationById('BrowserTracing')
444+
(client as BrowserClient).getIntegrationByName &&
445+
(client as BrowserClient).getIntegrationByName('BrowserTracing')
446446
) {
447447
// Initializers are called more than once in tests, causing the integrations to not be setup correctly.
448448
return;

packages/ember/tests/acceptance/sentry-replay-test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { visit } from '@ember/test-helpers';
22
import * as Sentry from '@sentry/ember';
3-
import type { ReplayContainer } from '@sentry/replay/build/npm/types/types';
3+
import type { BrowserClient, Replay } from '@sentry/ember';
44
import { setupApplicationTest } from 'ember-qunit';
55
import { module, test } from 'qunit';
66

@@ -13,10 +13,10 @@ module('Acceptance | Sentry Session Replay', function (hooks) {
1313
test('Test replay', async function (assert) {
1414
await visit('/replay');
1515

16-
const integration = Sentry.getCurrentHub().getIntegration(Sentry.Replay);
16+
const integration = Sentry.getClient<BrowserClient>()?.getIntegrationByName('Replay');
1717
assert.ok(integration);
1818

19-
const replay = (integration as Sentry.Replay)['_replay'] as ReplayContainer;
19+
const replay = (integration as Sentry.Replay)['_replay'] as Replay['_replay'];
2020

2121
assert.true(replay.isEnabled());
2222
assert.false(replay.isPaused());

packages/ember/tests/dummy/app/routes/replay.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ import * as Sentry from '@sentry/ember';
55
export default class ReplayRoute extends Route {
66
public async beforeModel(): Promise<void> {
77
const { Replay } = Sentry;
8-
9-
if (!Sentry.getCurrentHub().getIntegration(Replay)) {
10-
const client = Sentry.getCurrentHub().getClient() as BrowserClient;
8+
const client = Sentry.getClient<BrowserClient>();
9+
if (client && !client.getIntegrationByName('Replay')) {
1110
client.addIntegration(new Replay());
1211
}
1312
}

packages/feedback/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ import {Feedback} from '@sentry-internal/feedback';
212212

213213
function MyFeedbackButton() {
214214
const client = getCurrentHub().getClient<BrowserClient>();
215-
const feedback = client?.getIntegration(Feedback);
215+
const feedback = client?.getIntegrationByName('Feedback');
216216

217217
// Don't render custom feedback button if Feedback integration not installed
218218
if (!feedback) {
@@ -258,7 +258,7 @@ import {BrowserClient, getCurrentHub} from '@sentry/react';
258258
import {Feedback} from '@sentry-internal/feedback';
259259

260260
document.getElementById('my-feedback-form').addEventListener('submit', (event) => {
261-
const feedback = getCurrentHub().getClient<BrowserClient>()?.getIntegration(Feedback);
261+
const feedback = getCurrentHub().getClient<BrowserClient>()?.getIntegrationByName('Feedback');
262262
const formData = new FormData(event.currentTarget);
263263
feedback.sendFeedback(formData);
264264
event.preventDefault();

packages/integrations/src/offline.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ export class Offline implements Integration {
8181
}
8282

8383
const eventProcessor: EventProcessor = event => {
84+
// eslint-disable-next-line deprecation/deprecation
8485
if (this.hub && this.hub.getIntegration(Offline)) {
8586
// cache if we are positively offline
8687
if ('navigator' in WINDOW && 'onLine' in WINDOW.navigator && !WINDOW.navigator.onLine) {

packages/node-experimental/src/sdk/hub.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ export function getCurrentHub(): Hub {
9494
},
9595

9696
getIntegration<T extends Integration>(integration: IntegrationClass<T>): T | null {
97+
// eslint-disable-next-line deprecation/deprecation
9798
return getClient().getIntegration(integration);
9899
},
99100

packages/node-experimental/src/sdk/spanProcessor.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import type { Span } from '@opentelemetry/sdk-trace-base';
44
import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
55
import { SentrySpanProcessor, getClient, getSpanFinishScope } from '@sentry/opentelemetry';
66

7-
import { Http } from '../integrations/http';
8-
import { NodeFetch } from '../integrations/node-fetch';
7+
import type { Http } from '../integrations/http';
8+
import type { NodeFetch } from '../integrations/node-fetch';
99
import type { NodeExperimentalClient } from '../types';
1010
import { getIsolationScope } from './api';
1111
import { Scope } from './scope';
@@ -33,8 +33,8 @@ export class NodeExperimentalSentrySpanProcessor extends SentrySpanProcessor {
3333
/** @inheritDoc */
3434
protected _shouldSendSpanToSentry(span: Span): boolean {
3535
const client = getClient<NodeExperimentalClient>();
36-
const httpIntegration = client ? client.getIntegration(Http) : undefined;
37-
const fetchIntegration = client ? client.getIntegration(NodeFetch) : undefined;
36+
const httpIntegration = client ? client.getIntegrationByName<Http>('Http') : undefined;
37+
const fetchIntegration = client ? client.getIntegrationByName<NodeFetch>('NodeFetch') : undefined;
3838

3939
// If we encounter a client or server span with url & method, we assume this comes from the http instrumentation
4040
// In this case, if `shouldCreateSpansForRequests` is false, we want to _record_ the span but not _sample_ it,

packages/node-experimental/test/integration/transactions.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -515,8 +515,8 @@ describe('Integration | Transactions', () => {
515515
const hub = getCurrentHub();
516516
const client = hub.getClient() as NodeExperimentalClient;
517517

518-
jest.spyOn(client, 'getIntegration').mockImplementation(integrationClass => {
519-
if (integrationClass.name === 'Http') {
518+
jest.spyOn(client, 'getIntegrationByName').mockImplementation(name => {
519+
if (name === 'Http') {
520520
return {
521521
shouldCreateSpansForRequests: false,
522522
} as Http;
@@ -580,8 +580,8 @@ describe('Integration | Transactions', () => {
580580
const hub = getCurrentHub();
581581
const client = hub.getClient() as NodeExperimentalClient;
582582

583-
jest.spyOn(client, 'getIntegration').mockImplementation(integrationClass => {
584-
if (integrationClass.name === 'NodeFetch') {
583+
jest.spyOn(client, 'getIntegrationByName').mockImplementation(name => {
584+
if (name === 'NodeFetch') {
585585
return {
586586
shouldCreateSpansForRequests: false,
587587
} as NodeFetch;

packages/node/src/integrations/http.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ function _createWrappedRequestMethodFactory(
220220
req: http.ClientRequest,
221221
res?: http.IncomingMessage,
222222
): void {
223+
// eslint-disable-next-line deprecation/deprecation
223224
if (!getCurrentHub().getIntegration(Http)) {
224225
return;
225226
}

packages/node/src/integrations/undici/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ export class Undici implements Integration {
139139

140140
private _onRequestCreate = (message: unknown): void => {
141141
const hub = getCurrentHub();
142+
// eslint-disable-next-line deprecation/deprecation
142143
if (!hub.getIntegration(Undici)) {
143144
return;
144145
}
@@ -198,6 +199,7 @@ export class Undici implements Integration {
198199

199200
private _onRequestEnd = (message: unknown): void => {
200201
const hub = getCurrentHub();
202+
// eslint-disable-next-line deprecation/deprecation
201203
if (!hub.getIntegration(Undici)) {
202204
return;
203205
}
@@ -238,6 +240,7 @@ export class Undici implements Integration {
238240

239241
private _onRequestError = (message: unknown): void => {
240242
const hub = getCurrentHub();
243+
// eslint-disable-next-line deprecation/deprecation
241244
if (!hub.getIntegration(Undici)) {
242245
return;
243246
}

packages/node/test/integrations/undici.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ function setupTestServer() {
417417

418418
function patchUndici(userOptions: Partial<UndiciOptions>): () => void {
419419
try {
420-
const undici = hub.getClient()!.getIntegration(Undici);
420+
const undici = hub.getClient()!.getIntegrationByName!('Undici');
421421
// @ts-expect-error need to access private property
422422
options = { ...undici._options };
423423
// @ts-expect-error need to access private property
@@ -428,7 +428,7 @@ function patchUndici(userOptions: Partial<UndiciOptions>): () => void {
428428

429429
return () => {
430430
try {
431-
const undici = hub.getClient()!.getIntegration(Undici);
431+
const undici = hub.getClient()!.getIntegrationByName!('Undici');
432432
// @ts-expect-error Need to override readonly property
433433
undici!['_options'] = { ...options };
434434
} catch (_) {

0 commit comments

Comments
 (0)