Skip to content

Commit 8e652dc

Browse files
committed
ref(integrations): Refactor pluggable integrations to avoid setupOnce
1 parent cef3621 commit 8e652dc

File tree

4 files changed

+114
-82
lines changed

4 files changed

+114
-82
lines changed

packages/integrations/src/captureconsole.ts

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import type { EventProcessor, Hub, Integration } from '@sentry/types';
1+
import { captureException, captureMessage, getClient, withScope } from '@sentry/core';
2+
import type { CaptureContext, Client, EventProcessor, Hub, Integration } from '@sentry/types';
23
import {
34
CONSOLE_LEVELS,
45
GLOBAL_OBJ,
@@ -36,33 +37,37 @@ export class CaptureConsole implements Integration {
3637
/**
3738
* @inheritDoc
3839
*/
39-
public setupOnce(_: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void {
40+
public setupOnce(_: (callback: EventProcessor) => void, _getCurrentHub: () => Hub): void {
41+
// noop
42+
}
43+
44+
/** @inheritdoc */
45+
public client(client: Client): void {
4046
if (!('console' in GLOBAL_OBJ)) {
4147
return;
4248
}
4349

4450
const levels = this._levels;
4551

4652
addConsoleInstrumentationHandler(({ args, level }) => {
47-
if (!levels.includes(level)) {
53+
if (getClient() !== client || !levels.includes(level)) {
4854
return;
4955
}
5056

51-
const hub = getCurrentHub();
52-
53-
if (!hub.getIntegration(CaptureConsole)) {
54-
return;
55-
}
56-
57-
consoleHandler(hub, args, level);
57+
consoleHandler(args, level);
5858
});
5959
}
6060
}
6161

62-
function consoleHandler(hub: Hub, args: unknown[], level: string): void {
63-
hub.withScope(scope => {
64-
scope.setLevel(severityLevelFromString(level));
65-
scope.setExtra('arguments', args);
62+
function consoleHandler(args: unknown[], level: string): void {
63+
const captureContext: CaptureContext = {
64+
level: severityLevelFromString(level),
65+
extra: {
66+
arguments: args,
67+
},
68+
};
69+
70+
withScope(scope => {
6671
scope.addEventProcessor(event => {
6772
event.logger = 'console';
6873

@@ -74,18 +79,20 @@ function consoleHandler(hub: Hub, args: unknown[], level: string): void {
7479
return event;
7580
});
7681

77-
let message = safeJoin(args, ' ');
82+
if (level === 'assert' && args[0] === false) {
83+
const message = `Assertion failed: ${safeJoin(args.slice(1), ' ') || 'console.assert'}`;
84+
scope.setExtra('arguments', args.slice(1));
85+
captureMessage(message, captureContext);
86+
return;
87+
}
88+
7889
const error = args.find(arg => arg instanceof Error);
79-
if (level === 'assert') {
80-
if (args[0] === false) {
81-
message = `Assertion failed: ${safeJoin(args.slice(1), ' ') || 'console.assert'}`;
82-
scope.setExtra('arguments', args.slice(1));
83-
hub.captureMessage(message);
84-
}
85-
} else if (level === 'error' && error) {
86-
hub.captureException(error);
87-
} else {
88-
hub.captureMessage(message);
90+
if (level === 'error' && error) {
91+
captureException(error, captureContext);
92+
return;
8993
}
94+
95+
const message = safeJoin(args, ' ');
96+
captureMessage(message, captureContext);
9097
});
9198
}

packages/integrations/src/debug.ts

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Event, EventHint, EventProcessor, Hub, Integration } from '@sentry/types';
1+
import type { Client, Event, EventHint, EventProcessor, Hub, Integration } from '@sentry/types';
22
import { consoleSandbox } from '@sentry/utils';
33

44
interface DebugOptions {
@@ -38,32 +38,40 @@ export class Debug implements Integration {
3838
/**
3939
* @inheritDoc
4040
*/
41-
public setupOnce(_addGlobalEventProcessor: (eventProcessor: EventProcessor) => void, getCurrentHub: () => Hub): void {
42-
const client = getCurrentHub().getClient();
41+
public setupOnce(
42+
_addGlobalEventProcessor: (eventProcessor: EventProcessor) => void,
43+
_getCurrentHub: () => Hub,
44+
): void {
45+
// noop
46+
}
4347

44-
if (client && client.on) {
45-
client.on('beforeSendEvent', (event: Event, hint?: EventHint) => {
46-
if (this._options.debugger) {
47-
// eslint-disable-next-line no-debugger
48-
debugger;
49-
}
48+
/** @inheritdoc */
49+
public setup(client: Client): void {
50+
if (!client.on) {
51+
return;
52+
}
53+
54+
client.on('beforeSendEvent', (event: Event, hint?: EventHint) => {
55+
if (this._options.debugger) {
56+
// eslint-disable-next-line no-debugger
57+
debugger;
58+
}
5059

51-
/* eslint-disable no-console */
52-
consoleSandbox(() => {
53-
if (this._options.stringify) {
54-
console.log(JSON.stringify(event, null, 2));
55-
if (hint && Object.keys(hint).length) {
56-
console.log(JSON.stringify(hint, null, 2));
57-
}
58-
} else {
59-
console.log(event);
60-
if (hint && Object.keys(hint).length) {
61-
console.log(hint);
62-
}
60+
/* eslint-disable no-console */
61+
consoleSandbox(() => {
62+
if (this._options.stringify) {
63+
console.log(JSON.stringify(event, null, 2));
64+
if (hint && Object.keys(hint).length) {
65+
console.log(JSON.stringify(hint, null, 2));
6366
}
64-
});
65-
/* eslint-enable no-console */
67+
} else {
68+
console.log(event);
69+
if (hint && Object.keys(hint).length) {
70+
console.log(hint);
71+
}
72+
}
6673
});
67-
}
74+
/* eslint-enable no-console */
75+
});
6876
}
6977
}

packages/integrations/src/httpclient.ts

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { getClient, isSentryRequestUrl } from '@sentry/core';
1+
import { captureEvent, getClient, isSentryRequestUrl } from '@sentry/core';
22
import type {
3+
Client,
34
Event as SentryEvent,
45
EventProcessor,
56
Hub,
@@ -20,6 +21,7 @@ import { DEBUG_BUILD } from './debug-build';
2021

2122
export type HttpStatusCodeRange = [number, number] | number;
2223
export type HttpRequestTarget = string | RegExp;
24+
2325
interface HttpClientOptions {
2426
/**
2527
* HTTP status codes that should be considered failed.
@@ -55,11 +57,6 @@ export class HttpClient implements Integration {
5557

5658
private readonly _options: HttpClientOptions;
5759

58-
/**
59-
* Returns current hub.
60-
*/
61-
private _getCurrentHub?: () => Hub;
62-
6360
/**
6461
* @inheritDoc
6562
*
@@ -79,10 +76,14 @@ export class HttpClient implements Integration {
7976
*
8077
* @param options
8178
*/
82-
public setupOnce(_: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void {
83-
this._getCurrentHub = getCurrentHub;
84-
this._wrapFetch();
85-
this._wrapXHR();
79+
public setupOnce(_: (callback: EventProcessor) => void, _getCurrentHub: () => Hub): void {
80+
// noop
81+
}
82+
83+
/** @inheritdoc */
84+
public setup(client: Client): void {
85+
this._wrapFetch(client);
86+
this._wrapXHR(client);
8687
}
8788

8889
/**
@@ -93,13 +94,12 @@ export class HttpClient implements Integration {
9394
* @param requestInit The request init object
9495
*/
9596
private _fetchResponseHandler(requestInfo: RequestInfo, response: Response, requestInit?: RequestInit): void {
96-
if (this._getCurrentHub && this._shouldCaptureResponse(response.status, response.url)) {
97+
if (this._shouldCaptureResponse(response.status, response.url)) {
9798
const request = _getRequest(requestInfo, requestInit);
98-
const hub = this._getCurrentHub();
9999

100100
let requestHeaders, responseHeaders, requestCookies, responseCookies;
101101

102-
if (hub.shouldSendDefaultPii()) {
102+
if (_shouldSendDefaultPii()) {
103103
[{ headers: requestHeaders, cookies: requestCookies }, { headers: responseHeaders, cookies: responseCookies }] =
104104
[
105105
{ cookieHeader: 'Cookie', obj: request },
@@ -135,7 +135,7 @@ export class HttpClient implements Integration {
135135
responseCookies,
136136
});
137137

138-
hub.captureEvent(event);
138+
captureEvent(event);
139139
}
140140
}
141141

@@ -147,11 +147,10 @@ export class HttpClient implements Integration {
147147
* @param headers The HTTP headers
148148
*/
149149
private _xhrResponseHandler(xhr: XMLHttpRequest, method: string, headers: Record<string, string>): void {
150-
if (this._getCurrentHub && this._shouldCaptureResponse(xhr.status, xhr.responseURL)) {
150+
if (this._shouldCaptureResponse(xhr.status, xhr.responseURL)) {
151151
let requestHeaders, responseCookies, responseHeaders;
152-
const hub = this._getCurrentHub();
153152

154-
if (hub.shouldSendDefaultPii()) {
153+
if (_shouldSendDefaultPii()) {
155154
try {
156155
const cookieString = xhr.getResponseHeader('Set-Cookie') || xhr.getResponseHeader('set-cookie') || undefined;
157156

@@ -181,7 +180,7 @@ export class HttpClient implements Integration {
181180
responseCookies,
182181
});
183182

184-
hub.captureEvent(event);
183+
captureEvent(event);
185184
}
186185
}
187186

@@ -296,12 +295,16 @@ export class HttpClient implements Integration {
296295
/**
297296
* Wraps `fetch` function to capture request and response data
298297
*/
299-
private _wrapFetch(): void {
298+
private _wrapFetch(client: Client): void {
300299
if (!supportsNativeFetch()) {
301300
return;
302301
}
303302

304303
addFetchInstrumentationHandler(handlerData => {
304+
if (getClient() !== client) {
305+
return;
306+
}
307+
305308
const { response, args } = handlerData;
306309
const [requestInfo, requestInit] = args as [RequestInfo, RequestInit | undefined];
307310

@@ -316,12 +319,16 @@ export class HttpClient implements Integration {
316319
/**
317320
* Wraps XMLHttpRequest to capture request and response data
318321
*/
319-
private _wrapXHR(): void {
322+
private _wrapXHR(client: Client): void {
320323
if (!('XMLHttpRequest' in GLOBAL_OBJ)) {
321324
return;
322325
}
323326

324327
addXhrInstrumentationHandler(handlerData => {
328+
if (getClient() !== client) {
329+
return;
330+
}
331+
325332
const xhr = handlerData.xhr as SentryWrappedXMLHttpRequest & XMLHttpRequest;
326333

327334
const sentryXhrData = xhr[SENTRY_XHR_DATA_KEY];
@@ -418,3 +425,8 @@ function _getRequest(requestInfo: RequestInfo, requestInit?: RequestInit): Reque
418425

419426
return new Request(requestInfo, requestInit);
420427
}
428+
429+
function _shouldSendDefaultPii(): boolean {
430+
const client = getClient();
431+
return client ? Boolean(client.getOptions().sendDefaultPii) : false;
432+
}

packages/integrations/src/reportingobserver.ts

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import type { EventProcessor, Hub, Integration } from '@sentry/types';
1+
import { captureMessage, getClient, withScope } from '@sentry/core';
2+
import type { Client, EventProcessor, Hub, Integration } from '@sentry/types';
23
import { GLOBAL_OBJ, supportsReportingObserver } from '@sentry/utils';
34

45
const WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window;
@@ -39,6 +40,8 @@ interface InterventionReportBody {
3940
columnNumber?: number;
4041
}
4142

43+
const SETUP_CLIENTS: Client[] = [];
44+
4245
/** Reporting API integration - https://w3c.github.io/reporting/ */
4346
export class ReportingObserver implements Integration {
4447
/**
@@ -51,11 +54,6 @@ export class ReportingObserver implements Integration {
5154
*/
5255
public readonly name: string;
5356

54-
/**
55-
* Returns current hub.
56-
*/
57-
private _getCurrentHub?: () => Hub;
58-
5957
private readonly _types: ReportTypes[];
6058

6159
/**
@@ -74,13 +72,11 @@ export class ReportingObserver implements Integration {
7472
/**
7573
* @inheritDoc
7674
*/
77-
public setupOnce(_: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void {
75+
public setupOnce(_: (callback: EventProcessor) => void, _getCurrentHub: () => Hub): void {
7876
if (!supportsReportingObserver()) {
7977
return;
8078
}
8179

82-
this._getCurrentHub = getCurrentHub;
83-
8480
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
8581
const observer = new (WINDOW as any).ReportingObserver(this.handler.bind(this), {
8682
buffered: true,
@@ -91,16 +87,25 @@ export class ReportingObserver implements Integration {
9187
observer.observe();
9288
}
9389

90+
/** @inheritdoc */
91+
public setup(client: Client): void {
92+
if (!supportsReportingObserver()) {
93+
return;
94+
}
95+
96+
SETUP_CLIENTS.push(client);
97+
}
98+
9499
/**
95100
* @inheritDoc
96101
*/
97102
public handler(reports: Report[]): void {
98-
const hub = this._getCurrentHub && this._getCurrentHub();
99-
if (!hub || !hub.getIntegration(ReportingObserver)) {
103+
if (!SETUP_CLIENTS.includes(getClient() as Client)) {
100104
return;
101105
}
106+
102107
for (const report of reports) {
103-
hub.withScope(scope => {
108+
withScope(scope => {
104109
scope.setExtra('url', report.url);
105110

106111
const label = `ReportingObserver [${report.type}]`;
@@ -129,7 +134,7 @@ export class ReportingObserver implements Integration {
129134
}
130135
}
131136

132-
hub.captureMessage(`${label}: ${details}`);
137+
captureMessage(`${label}: ${details}`);
133138
});
134139
}
135140
}

0 commit comments

Comments
 (0)