Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: upgrade to Sentry 8 (#25999) [cherry-pick] #26618

Merged
merged 2 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 21 additions & 66 deletions app/scripts/lib/sentry-filter-events.ts
Original file line number Diff line number Diff line change
@@ -1,73 +1,28 @@
import {
Event as SentryEvent,
EventProcessor,
Hub,
Integration,
} from '@sentry/types';
import { Event as SentryEvent, Integration } from '@sentry/types';
import { logger } from '@sentry/utils';

const NAME = 'FilterEvents';

/**
* Filter events when MetaMetrics is disabled.
*
* @param options - Options bag.
* @param options.getMetaMetricsEnabled - Function that returns whether MetaMetrics is enabled.
*/
export class FilterEvents implements Integration {
/**
* Property that holds the integration name.
*/
public static id = 'FilterEvents';

/**
* Another property that holds the integration name.
*
* I don't know why this exists, but the other Sentry integrations have it.
*/
public name: string = FilterEvents.id;

/**
* A function that returns whether MetaMetrics is enabled. This should also
* return `false` if state has not yet been initialzed.
*
* @returns `true` if MetaMask's state has been initialized, and MetaMetrics
* is enabled, `false` otherwise.
*/
private getMetaMetricsEnabled: () => Promise<boolean>;

/**
* @param options - Constructor options.
* @param options.getMetaMetricsEnabled - A function that returns whether
* MetaMetrics is enabled. This should also return `false` if state has not
* yet been initialzed.
*/
constructor({
getMetaMetricsEnabled,
}: {
getMetaMetricsEnabled: () => Promise<boolean>;
}) {
this.getMetaMetricsEnabled = getMetaMetricsEnabled;
}

/**
* Setup the integration.
*
* @param addGlobalEventProcessor - A function that allows adding a global
* event processor.
* @param getCurrentHub - A function that returns the current Sentry hub.
*/
public setupOnce(
addGlobalEventProcessor: (callback: EventProcessor) => void,
getCurrentHub: () => Hub,
): void {
addGlobalEventProcessor(async (currentEvent: SentryEvent) => {
// Sentry integrations use the Sentry hub to get "this" references, for
// reasons I don't fully understand.
// eslint-disable-next-line consistent-this
const self = getCurrentHub().getIntegration(FilterEvents);
if (self) {
if (!(await self.getMetaMetricsEnabled())) {
logger.warn(`Event dropped due to MetaMetrics setting.`);
return null;
}
export function filterEvents({
getMetaMetricsEnabled,
}: {
getMetaMetricsEnabled: () => Promise<boolean>;
}): Integration {
return {
name: NAME,
processEvent: async (event: SentryEvent) => {
if (!(await getMetaMetricsEnabled())) {
logger.warn(`Event dropped due to MetaMetrics setting.`);
return null;
}
return currentEvent;
});
}

return event;
},
};
}
39 changes: 23 additions & 16 deletions app/scripts/lib/setupSentry.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import * as Sentry from '@sentry/browser';
import { Dedupe, ExtraErrorData } from '@sentry/integrations';
import browser from 'webextension-polyfill';
import { isManifestV3 } from '../../../shared/modules/mv3.utils';
import { FilterEvents } from './sentry-filter-events';
import { filterEvents } from './sentry-filter-events';
import extractEthjsErrorMessage from './extractEthjsErrorMessage';

let installType = 'unknown';
Expand Down Expand Up @@ -190,6 +189,14 @@ export default function setupSentry({ release, getState }) {
console.log('Error getting extension installType', error);
});

/**
* Sentry throws on initialization as it wants to avoid polluting the global namespace and
* potentially clashing with a website also using Sentry, but this could only happen in the content script.
* This emulates NW.js which disables these validations.
* https://docs.sentry.io/platforms/javascript/best-practices/shared-environments/
*/
globalThis.nw = {};

Sentry.init({
dsn: sentryTarget,
debug: METAMASK_DEBUG,
Expand Down Expand Up @@ -233,10 +240,10 @@ export default function setupSentry({ release, getState }) {
*
* @see https://github.com/MetaMask/metamask-extension/pull/15677
*/
new FilterEvents({ getMetaMetricsEnabled }),
new Dedupe(),
new ExtraErrorData(),
new Sentry.BrowserProfilingIntegration(),
filterEvents({ getMetaMetricsEnabled }),
Sentry.dedupeIntegration(),
Sentry.extraErrorDataIntegration(),
Sentry.browserProfilingIntegration(),
],
release,
/**
Expand Down Expand Up @@ -265,11 +272,11 @@ export default function setupSentry({ release, getState }) {
* a new sentry session.
*/
const startSession = async () => {
const hub = Sentry.getCurrentHub?.();
const options = hub.getClient?.().getOptions?.() ?? {};
if (hub && (await getSentryEnabled()) === true) {
const client = Sentry.getClient();
const options = client?.getOptions?.() ?? {};
if (client && (await getSentryEnabled()) === true) {
options.autoSessionTracking = true;
hub.startSession();
Sentry.startSession();
}
};

Expand All @@ -279,11 +286,11 @@ export default function setupSentry({ release, getState }) {
* the current sentry session.
*/
const endSession = async () => {
const hub = Sentry.getCurrentHub?.();
const options = hub.getClient?.().getOptions?.() ?? {};
if (hub && (await getSentryEnabled()) === false) {
const client = Sentry.getClient();
const options = client?.getOptions?.() ?? {};
if (client && (await getSentryEnabled()) === false) {
options.autoSessionTracking = false;
hub.endSession();
Sentry.endSession();
}
};

Expand All @@ -293,8 +300,8 @@ export default function setupSentry({ release, getState }) {
* the Sentry client.
*/
const toggleSession = async () => {
const hub = Sentry.getCurrentHub?.();
const options = hub.getClient?.().getOptions?.() ?? {
const client = Sentry.getClient();
const options = client?.getOptions?.() ?? {
autoSessionTracking: false,
};
const isSentryEnabled = await getSentryEnabled();
Expand Down
2 changes: 2 additions & 0 deletions development/build/scripts.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ const scuttlingConfigBase = {
encodeURIComponent: '',
console: '',
crypto: '',
Map: '',
// {clear/set}Timeout are "this sensitive"
clearTimeout: 'window',
setTimeout: 'window',
Expand All @@ -88,6 +89,7 @@ const scuttlingConfigBase = {
appState: '',
extra: '',
stateHooks: '',
nw: '',
},
};

Expand Down
118 changes: 85 additions & 33 deletions lavamoat/browserify/beta/policy.json
Original file line number Diff line number Diff line change
Expand Up @@ -2958,118 +2958,170 @@
},
"@sentry/browser": {
"globals": {
"TextDecoder": true,
"TextEncoder": true,
"XMLHttpRequest": true,
"PerformanceObserver.supportedEntryTypes.includes": true,
"Request": true,
"URL": true,
"XMLHttpRequest.prototype": true,
"__SENTRY_DEBUG__": true,
"__SENTRY_RELEASE__": true,
"addEventListener": true,
"console.error": true,
"indexedDB.open": true,
"performance.timeOrigin": true,
"setTimeout": true
},
"packages": {
"@sentry/browser>@sentry-internal/tracing": true,
"@sentry/browser>@sentry-internal/browser-utils": true,
"@sentry/browser>@sentry-internal/feedback": true,
"@sentry/browser>@sentry-internal/replay": true,
"@sentry/browser>@sentry-internal/replay-canvas": true,
"@sentry/browser>@sentry/core": true,
"@sentry/browser>@sentry/replay": true,
"@sentry/utils": true
}
},
"@sentry/browser>@sentry-internal/tracing": {
"@sentry/browser>@sentry-internal/browser-utils": {
"globals": {
"Headers": true,
"PerformanceEventTiming.prototype": true,
"PerformanceObserver": true,
"Request": true,
"XMLHttpRequest.prototype": true,
"__SENTRY_DEBUG__": true,
"addEventListener": true,
"performance.getEntriesByType": true,
"removeEventListener": true
"clearTimeout": true,
"performance": true,
"removeEventListener": true,
"setTimeout": true
},
"packages": {
"@sentry/browser>@sentry/core": true,
"@sentry/utils": true
}
},
"@sentry/browser>@sentry/core": {
"@sentry/browser>@sentry-internal/feedback": {
"globals": {
"FormData": true,
"HTMLFormElement": true,
"__SENTRY_DEBUG__": true,
"__SENTRY_TRACING__": true,
"clearInterval": true,
"cancelAnimationFrame": true,
"clearTimeout": true,
"console.warn": true,
"setInterval": true,
"document.createElement": true,
"document.createElementNS": true,
"document.createTextNode": true,
"isSecureContext": true,
"requestAnimationFrame": true,
"setTimeout": true
},
"packages": {
"@sentry/browser>@sentry/core": true,
"@sentry/utils": true
}
},
"@sentry/browser>@sentry/replay": {
"@sentry/browser>@sentry-internal/replay": {
"globals": {
"Blob": true,
"CSSConditionRule": true,
"CSSGroupingRule": true,
"CSSMediaRule": true,
"CSSRule": true,
"CSSSupportsRule": true,
"Document": true,
"DragEvent": true,
"Element": true,
"FormData": true,
"HTMLCanvasElement": true,
"HTMLElement.prototype": true,
"HTMLElement": true,
"HTMLFormElement": true,
"HTMLImageElement": true,
"HTMLInputElement.prototype": true,
"HTMLOptionElement.prototype": true,
"HTMLSelectElement.prototype": true,
"HTMLTextAreaElement.prototype": true,
"Headers": true,
"ImageData": true,
"MouseEvent": true,
"MutationObserver": true,
"Node.DOCUMENT_FRAGMENT_NODE": true,
"Node.prototype.contains": true,
"PerformanceObserver": true,
"PointerEvent": true,
"TextEncoder": true,
"URL": true,
"URLSearchParams": true,
"Worker": true,
"Zone": true,
"__RRWEB_EXCLUDE_IFRAME__": true,
"__RRWEB_EXCLUDE_SHADOW_DOM__": true,
"__SENTRY_DEBUG__": true,
"__SENTRY_EXCLUDE_REPLAY_WORKER__": true,
"__rrMutationObserver": true,
"addEventListener": true,
"clearTimeout": true,
"console.debug": true,
"console.error": true,
"console.warn": true,
"customElements.get": true,
"document": true,
"innerHeight": true,
"innerWidth": true,
"location.href": true,
"pageXOffset": true,
"pageYOffset": true,
"requestAnimationFrame": true,
"setTimeout": true
"location.origin": true,
"parent": true
},
"packages": {
"@sentry/browser>@sentry-internal/browser-utils": true,
"@sentry/browser>@sentry/core": true,
"@sentry/utils": true,
"browserify>process": true
"@sentry/utils": true
}
},
"@sentry/browser>@sentry-internal/replay-canvas": {
"globals": {
"Blob": true,
"HTMLCanvasElement": true,
"HTMLImageElement": true,
"ImageData": true,
"URL.createObjectURL": true,
"WeakRef": true,
"Worker": true,
"cancelAnimationFrame": true,
"console.error": true,
"createImageBitmap": true,
"document": true
},
"packages": {
"@sentry/browser>@sentry/core": true,
"@sentry/utils": true
}
},
"@sentry/browser>@sentry/core": {
"globals": {
"Headers": true,
"Request": true,
"URL": true,
"__SENTRY_DEBUG__": true,
"__SENTRY_TRACING__": true,
"clearInterval": true,
"clearTimeout": true,
"console.log": true,
"console.warn": true,
"setInterval": true,
"setTimeout": true
},
"packages": {
"@sentry/utils": true
}
},
"@sentry/utils": {
"globals": {
"CustomEvent": true,
"DOMError": true,
"DOMException": true,
"EdgeRuntime": true,
"Element": true,
"ErrorEvent": true,
"Event": true,
"HTMLElement": true,
"Headers": true,
"Request": true,
"Response": true,
"TextDecoder": true,
"TextEncoder": true,
"URL": true,
"XMLHttpRequest.prototype": true,
"__SENTRY_BROWSER_BUNDLE__": true,
"__SENTRY_DEBUG__": true,
"clearTimeout": true,
"console.error": true,
"document": true,
"setInterval": true,
"setTimeout": true
},
"packages": {
Expand Down
Loading