Skip to content

Commit ffb33f9

Browse files
committed
feat(core): Add client.init() to replace client.setupIntegrations()
1 parent 15ab8ee commit ffb33f9

File tree

10 files changed

+128
-21
lines changed

10 files changed

+128
-21
lines changed

MIGRATION.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ 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 `client.setupIntegrations()`
12+
13+
Instead, use the new `client.init()` method. You should probably not use this directly and instead use `Sentry.init()`, which calls this under the hood. But if you have a special use case that requires that, you can call `client.init()` instead now.
14+
1115
## Deprecate `scope.getSpan()` and `scope.setSpan()`
1216

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

packages/browser/test/unit/sdk.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ jest.mock('@sentry/core', () => {
4242
return new Scope();
4343
},
4444
bindClient(client: Client): boolean {
45-
client.setupIntegrations();
45+
client.init!();
4646
return true;
4747
},
4848
};

packages/core/src/baseclient.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -314,12 +314,19 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
314314
}
315315

316316
/**
317-
* Sets up the integrations
317+
* This is an internal function to setup all integrations that should run on the client.
318+
* @deprecated Use `client.init()` instead.
318319
*/
319320
public setupIntegrations(forceInitialize?: boolean): void {
320321
if ((forceInitialize && !this._integrationsInitialized) || (this._isEnabled() && !this._integrationsInitialized)) {
321-
this._integrations = setupIntegrations(this, this._options.integrations);
322-
this._integrationsInitialized = true;
322+
this._setupIntegrations();
323+
}
324+
}
325+
326+
/** @inheritdoc */
327+
public init(): void {
328+
if (this._isEnabled()) {
329+
this._setupIntegrations();
323330
}
324331
}
325332

@@ -512,6 +519,13 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
512519

513520
/* eslint-enable @typescript-eslint/unified-signatures */
514521

522+
/** Setup integrations for this client. */
523+
protected _setupIntegrations(): void {
524+
this._integrations = setupIntegrations(this, this._options.integrations);
525+
// TODO v8: We don't need this flag anymore
526+
this._integrationsInitialized = true;
527+
}
528+
515529
/** Updates existing session based on the provided event */
516530
protected _updateSessionFromEvent(session: Session, event: Event): void {
517531
let crashed = false;

packages/core/src/hub.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,9 @@ export class Hub implements HubInterface {
167167
const top = this.getStackTop();
168168
top.client = client;
169169
top.scope.setClient(client);
170+
// eslint-disable-next-line deprecation/deprecation
170171
if (client && client.setupIntegrations) {
172+
// eslint-disable-next-line deprecation/deprecation
171173
client.setupIntegrations();
172174
}
173175
}

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

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -671,7 +671,7 @@ describe('BaseClient', () => {
671671
test('adds installed integrations to sdk info', () => {
672672
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, integrations: [new TestIntegration()] });
673673
const client = new TestClient(options);
674-
client.setupIntegrations();
674+
client.init();
675675

676676
client.captureEvent({ message: 'message' });
677677

@@ -685,7 +685,7 @@ describe('BaseClient', () => {
685685

686686
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, integrations: [new TestIntegration()] });
687687
const client = new TestClient(options);
688-
client.setupIntegrations();
688+
client.init();
689689
client.addIntegration(new AdHocIntegration());
690690

691691
client.captureException(new Error('test exception'));
@@ -706,7 +706,7 @@ describe('BaseClient', () => {
706706
integrations: [new TestIntegration(), null, undefined],
707707
});
708708
const client = new TestClient(options);
709-
client.setupIntegrations();
709+
client.init();
710710

711711
client.captureEvent({ message: 'message' });
712712

@@ -1482,24 +1482,48 @@ describe('BaseClient', () => {
14821482

14831483
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, integrations: [new TestIntegration()] });
14841484
const client = new TestClient(options);
1485+
// eslint-disable-next-line deprecation/deprecation
14851486
client.setupIntegrations();
14861487

14871488
expect(Object.keys((client as any)._integrations).length).toEqual(1);
14881489
expect(client.getIntegration(TestIntegration)).toBeTruthy();
14891490
});
14901491

1491-
test('skips installation if DSN is not provided', () => {
1492+
test('sets up each integration on `init` call', () => {
1493+
expect.assertions(2);
1494+
1495+
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, integrations: [new TestIntegration()] });
1496+
const client = new TestClient(options);
1497+
client.init();
1498+
1499+
expect(Object.keys((client as any)._integrations).length).toEqual(1);
1500+
expect(client.getIntegration(TestIntegration)).toBeTruthy();
1501+
});
1502+
1503+
test('skips installation for `setupIntegrations()` if DSN is not provided', () => {
14921504
expect.assertions(2);
14931505

14941506
const options = getDefaultTestClientOptions({ integrations: [new TestIntegration()] });
14951507
const client = new TestClient(options);
1508+
// eslint-disable-next-line deprecation/deprecation
14961509
client.setupIntegrations();
14971510

14981511
expect(Object.keys((client as any)._integrations).length).toEqual(0);
14991512
expect(client.getIntegration(TestIntegration)).toBeFalsy();
15001513
});
15011514

1502-
test('skips installation if `enabled` is set to `false`', () => {
1515+
test('skips installation for `init()` if DSN is not provided', () => {
1516+
expect.assertions(2);
1517+
1518+
const options = getDefaultTestClientOptions({ integrations: [new TestIntegration()] });
1519+
const client = new TestClient(options);
1520+
client.init();
1521+
1522+
expect(Object.keys((client as any)._integrations).length).toEqual(0);
1523+
expect(client.getIntegration(TestIntegration)).toBeFalsy();
1524+
});
1525+
1526+
test('skips installation for `setupIntegrations()` if `enabled` is set to `false`', () => {
15031527
expect.assertions(2);
15041528

15051529
const options = getDefaultTestClientOptions({
@@ -1508,12 +1532,28 @@ describe('BaseClient', () => {
15081532
integrations: [new TestIntegration()],
15091533
});
15101534
const client = new TestClient(options);
1535+
// eslint-disable-next-line deprecation/deprecation
15111536
client.setupIntegrations();
15121537

15131538
expect(Object.keys((client as any)._integrations).length).toEqual(0);
15141539
expect(client.getIntegration(TestIntegration)).toBeFalsy();
15151540
});
15161541

1542+
test('skips installation for `init()` if `enabled` is set to `false`', () => {
1543+
expect.assertions(2);
1544+
1545+
const options = getDefaultTestClientOptions({
1546+
dsn: PUBLIC_DSN,
1547+
enabled: false,
1548+
integrations: [new TestIntegration()],
1549+
});
1550+
const client = new TestClient(options);
1551+
client.init();
1552+
1553+
expect(Object.keys((client as any)._integrations).length).toEqual(0);
1554+
expect(client.getIntegration(TestIntegration)).toBeFalsy();
1555+
});
1556+
15171557
test('skips installation if integrations are already installed', () => {
15181558
expect.assertions(4);
15191559

@@ -1523,17 +1563,41 @@ describe('BaseClient', () => {
15231563
const setupIntegrationsHelper = jest.spyOn(integrationModule, 'setupIntegrations');
15241564

15251565
// it should install the first time, because integrations aren't yet installed...
1566+
// eslint-disable-next-line deprecation/deprecation
15261567
client.setupIntegrations();
15271568

15281569
expect(Object.keys((client as any)._integrations).length).toEqual(1);
15291570
expect(client.getIntegration(TestIntegration)).toBeTruthy();
15301571
expect(setupIntegrationsHelper).toHaveBeenCalledTimes(1);
15311572

15321573
// ...but it shouldn't try to install a second time
1574+
// eslint-disable-next-line deprecation/deprecation
15331575
client.setupIntegrations();
15341576

15351577
expect(setupIntegrationsHelper).toHaveBeenCalledTimes(1);
15361578
});
1579+
1580+
test('does not add integrations twice when calling `init` multiple times', () => {
1581+
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, integrations: [new TestIntegration()] });
1582+
const client = new TestClient(options);
1583+
// note: not the `Client` method `setupIntegrations`, but the free-standing function which that method calls
1584+
const setupIntegrationsHelper = jest.spyOn(integrationModule, 'setupIntegrations');
1585+
1586+
// it should install the first time, because integrations aren't yet installed...
1587+
client.init();
1588+
1589+
expect(Object.keys((client as any)._integrations).length).toEqual(1);
1590+
expect(client.getIntegration(TestIntegration)).toBeTruthy();
1591+
expect(setupIntegrationsHelper).toHaveBeenCalledTimes(1);
1592+
1593+
client.init();
1594+
1595+
// is called again...
1596+
expect(setupIntegrationsHelper).toHaveBeenCalledTimes(2);
1597+
1598+
// but integrations are only added once anyhow!
1599+
expect(client['_integrations']).toEqual({ TestIntegration: expect.any(TestIntegration) });
1600+
});
15371601
});
15381602

15391603
describe('flush/close', () => {

packages/core/test/lib/integrations/inboundfilters.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ function createInboundFiltersEventProcessor(
3737
}),
3838
);
3939

40-
client.setupIntegrations();
40+
client.init();
4141

4242
const eventProcessors = client['_eventProcessors'];
4343
const eventProcessor = eventProcessors.find(processor => processor.id === 'InboundFilters');

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
getSentryRelease,
77
makeNodeTransport,
88
} from '@sentry/node';
9-
import type { Integration } from '@sentry/types';
9+
import type { Client, Integration } from '@sentry/types';
1010
import {
1111
consoleSandbox,
1212
dropUndefinedKeys,
@@ -67,7 +67,9 @@ export function init(options: NodeExperimentalOptions | undefined = {}): void {
6767
// unless somebody specifically sets a different one on a scope/isolations cope
6868
getGlobalScope().setClient(client);
6969

70-
client.setupIntegrations();
70+
if (isEnabled(client)) {
71+
client.init();
72+
}
7173

7274
if (options.autoSessionTracking) {
7375
startSessionTracking();
@@ -79,7 +81,11 @@ export function init(options: NodeExperimentalOptions | undefined = {}): void {
7981
const client = getClient();
8082
if (client.addIntegration) {
8183
// force integrations to be setup even if no DSN was set
82-
client.setupIntegrations(true);
84+
// If they have already been added before, they will be ignored anyhow
85+
const integrations = client.getOptions().integrations;
86+
for (const integration of integrations) {
87+
client.addIntegration(integration);
88+
}
8389
client.addIntegration(
8490
new Integrations.Spotlight({
8591
sidecarUrl: typeof options.spotlight === 'string' ? options.spotlight : undefined,
@@ -213,3 +219,7 @@ function startSessionTracking(): void {
213219
}
214220
});
215221
}
222+
223+
function isEnabled(client: Client): boolean {
224+
return client.getOptions().enabled !== false && client.getTransport() !== undefined;
225+
}

packages/node/src/sdk.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,11 @@ export function init(options: NodeOptions = {}): void {
183183
const client = getClient();
184184
if (client && client.addIntegration) {
185185
// force integrations to be setup even if no DSN was set
186-
client.setupIntegrations(true);
186+
// If they have already been added before, they will be ignored anyhow
187+
const integrations = client.getOptions().integrations;
188+
for (const integration of integrations) {
189+
client.addIntegration(integration);
190+
}
187191
client.addIntegration(
188192
new Spotlight({ sidecarUrl: typeof options.spotlight === 'string' ? options.spotlight : undefined }),
189193
);

packages/node/test/integrations/localvariables.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ describeIf(NODE_VERSION.major >= 18)('LocalVariables', () => {
166166
});
167167

168168
const client = new NodeClient(options);
169-
client.setupIntegrations(true);
169+
client.init();
170170

171171
const eventProcessors = client['_eventProcessors'];
172172
const eventProcessor = eventProcessors.find(processor => processor.id === 'LocalVariables');
@@ -257,7 +257,7 @@ describeIf(NODE_VERSION.major >= 18)('LocalVariables', () => {
257257
});
258258

259259
const client = new NodeClient(options);
260-
client.setupIntegrations(true);
260+
client.init();
261261

262262
await session.runPause(exceptionEvent100Frames);
263263

@@ -282,7 +282,7 @@ describeIf(NODE_VERSION.major >= 18)('LocalVariables', () => {
282282
});
283283

284284
const client = new NodeClient(options);
285-
client.setupIntegrations(true);
285+
client.init();
286286

287287
const nonExceptionEvent = {
288288
method: exceptionEvent.method,
@@ -303,7 +303,7 @@ describeIf(NODE_VERSION.major >= 18)('LocalVariables', () => {
303303
});
304304

305305
const client = new NodeClient(options);
306-
client.setupIntegrations(true);
306+
client.init();
307307

308308
const eventProcessors = client['_eventProcessors'];
309309
const eventProcessor = eventProcessors.find(processor => processor.id === 'LocalVariables');
@@ -319,7 +319,7 @@ describeIf(NODE_VERSION.major >= 18)('LocalVariables', () => {
319319
});
320320

321321
const client = new NodeClient(options);
322-
client.setupIntegrations(true);
322+
client.init();
323323

324324
const eventProcessors = client['_eventProcessors'];
325325
const eventProcessor = eventProcessors.find(processor => processor.id === 'LocalVariables');
@@ -340,7 +340,7 @@ describeIf(NODE_VERSION.major >= 18)('LocalVariables', () => {
340340
});
341341

342342
const client = new NodeClient(options);
343-
client.setupIntegrations(true);
343+
client.init();
344344

345345
await session.runPause(exceptionEvent);
346346
await session.runPause(exceptionEvent);

packages/types/src/client.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,18 @@ export interface Client<O extends ClientOptions = ClientOptions> {
151151
* */
152152
addIntegration?(integration: Integration): void;
153153

154-
/** This is an internal function to setup all integrations that should run on the client */
154+
/**
155+
* This is an internal function to setup all integrations that should run on the client.
156+
* @deprecated Use `client.init()` instead.
157+
*/
155158
setupIntegrations(forceInitialize?: boolean): void;
156159

160+
/**
161+
* Initialize this client.
162+
* Call this after the client was set on a scope.
163+
*/
164+
init?(): void;
165+
157166
/** Creates an {@link Event} from all inputs to `captureException` and non-primitive inputs to `captureMessage`. */
158167
// eslint-disable-next-line @typescript-eslint/no-explicit-any
159168
eventFromException(exception: any, hint?: EventHint): PromiseLike<Event>;

0 commit comments

Comments
 (0)