@sentry/browser
Version:
Official Sentry SDK for browsers
136 lines (129 loc) • 4.42 kB
JavaScript
import { defineIntegration, debug, isPlainObject } from '@sentry/core';
import { DEBUG_BUILD } from '../debug-build.js';
import { WINDOW } from '../helpers.js';
const INTEGRATION_NAME = 'WebWorker';
/**
* Use this integration to set up Sentry with web workers.
*
* IMPORTANT: This integration must be added **before** you start listening to
* any messages from the worker. Otherwise, your message handlers will receive
* messages from the Sentry SDK which you need to ignore.
*
* This integration only has an effect, if you call `Sentry.registerWorker(self)`
* from within the worker(s) you're adding to the integration.
*
* Given that you want to initialize the SDK as early as possible, you most likely
* want to add this integration **after** initializing the SDK:
*
* @example:
* ```ts filename={main.js}
* import * as Sentry from '@sentry/<your-sdk>';
*
* // some time earlier:
* Sentry.init(...)
*
* // 1. Initialize the worker
* const worker = new Worker(new URL('./worker.ts', import.meta.url));
*
* // 2. Add the integration
* const webWorkerIntegration = Sentry.webWorkerIntegration({ worker });
* Sentry.addIntegration(webWorkerIntegration);
*
* // 3. Register message listeners on the worker
* worker.addEventListener('message', event => {
* // ...
* });
* ```
*
* If you initialize multiple workers at the same time, you can also pass an array of workers
* to the integration:
*
* ```ts filename={main.js}
* const webWorkerIntegration = Sentry.webWorkerIntegration({ worker: [worker1, worker2] });
* Sentry.addIntegration(webWorkerIntegration);
* ```
*
* If you have any additional workers that you initialize at a later point,
* you can add them to the integration as follows:
*
* ```ts filename={main.js}
* const webWorkerIntegration = Sentry.webWorkerIntegration({ worker: worker1 });
* Sentry.addIntegration(webWorkerIntegration);
*
* // sometime later:
* webWorkerIntegration.addWorker(worker2);
* ```
*
* Of course, you can also directly add the integration in Sentry.init:
* ```ts filename={main.js}
* import * as Sentry from '@sentry/<your-sdk>';
*
* // 1. Initialize the worker
* const worker = new Worker(new URL('./worker.ts', import.meta.url));
*
* // 2. Initialize the SDK
* Sentry.init({
* integrations: [Sentry.webWorkerIntegration({ worker })]
* });
*
* // 3. Register message listeners on the worker
* worker.addEventListener('message', event => {
* // ...
* });
* ```
*
* @param options {WebWorkerIntegrationOptions} Integration options:
* - `worker`: The worker instance.
*/
const webWorkerIntegration = defineIntegration(({ worker }) => ({
name: INTEGRATION_NAME,
setupOnce: () => {
(Array.isArray(worker) ? worker : [worker]).forEach(w => listenForSentryDebugIdMessages(w));
},
addWorker: (worker) => listenForSentryDebugIdMessages(worker),
})) ;
function listenForSentryDebugIdMessages(worker) {
worker.addEventListener('message', event => {
if (isSentryDebugIdMessage(event.data)) {
event.stopImmediatePropagation(); // other listeners should not receive this message
DEBUG_BUILD && debug.log('Sentry debugId web worker message received', event.data);
WINDOW._sentryDebugIds = {
...event.data._sentryDebugIds,
// debugIds of the main thread have precedence over the worker's in case of a collision.
...WINDOW._sentryDebugIds,
};
}
});
}
/**
* Use this function to register the worker with the Sentry SDK.
*
* @example
* ```ts filename={worker.js}
* import * as Sentry from '@sentry/<your-sdk>';
*
* // Do this as early as possible in your worker.
* Sentry.registerWorker({ self });
*
* // continue setting up your worker
* self.postMessage(...)
* ```
* @param options {RegisterWebWorkerOptions} Integration options:
* - `self`: The worker instance you're calling this function from (self).
*/
function registerWebWorker({ self }) {
self.postMessage({
_sentryMessage: true,
_sentryDebugIds: self._sentryDebugIds ?? undefined,
});
}
function isSentryDebugIdMessage(eventData) {
return (
isPlainObject(eventData) &&
eventData._sentryMessage === true &&
'_sentryDebugIds' in eventData &&
(isPlainObject(eventData._sentryDebugIds) || eventData._sentryDebugIds === undefined)
);
}
export { INTEGRATION_NAME, registerWebWorker, webWorkerIntegration };
//# sourceMappingURL=webWorker.js.map