Skip to content

fix: Ensure we never mutate options passed to init #9162

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

Merged
merged 1 commit into from
Oct 3, 2023
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
32 changes: 17 additions & 15 deletions packages/angular-ivy/src/sdk.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { VERSION } from '@angular/core';
import type { BrowserOptions } from '@sentry/browser';
import { defaultIntegrations, init as browserInit, SDK_VERSION, setContext } from '@sentry/browser';
import type { SdkMetadata } from '@sentry/types';
import { logger } from '@sentry/utils';

import { IS_DEBUG_BUILD } from './flags';
Expand All @@ -9,8 +10,21 @@ import { IS_DEBUG_BUILD } from './flags';
* Inits the Angular SDK
*/
export function init(options: BrowserOptions): void {
options._metadata = options._metadata || {};
options._metadata.sdk = {
const opts = {
_metadata: {} as SdkMetadata,
// Filter out TryCatch integration as it interferes with our Angular `ErrorHandler`:
// TryCatch would catch certain errors before they reach the `ErrorHandler` and thus provide a
// lower fidelity error than what `SentryErrorHandler` (see errorhandler.ts) would provide.
// see:
// - https://github.com/getsentry/sentry-javascript/issues/5417#issuecomment-1453407097
// - https://github.com/getsentry/sentry-javascript/issues/2744
defaultIntegrations: defaultIntegrations.filter(integration => {
return integration.name !== 'TryCatch';
}),
...options,
};

opts._metadata.sdk = opts._metadata.sdk || {
name: 'sentry.javascript.angular-ivy',
packages: [
{
Expand All @@ -21,20 +35,8 @@ export function init(options: BrowserOptions): void {
version: SDK_VERSION,
};

// Filter out TryCatch integration as it interferes with our Angular `ErrorHandler`:
// TryCatch would catch certain errors before they reach the `ErrorHandler` and thus provide a
// lower fidelity error than what `SentryErrorHandler` (see errorhandler.ts) would provide.
// see:
// - https://github.com/getsentry/sentry-javascript/issues/5417#issuecomment-1453407097
// - https://github.com/getsentry/sentry-javascript/issues/2744
if (options.defaultIntegrations === undefined) {
options.defaultIntegrations = defaultIntegrations.filter(integration => {
return integration.name !== 'TryCatch';
});
}

checkAndSetAngularVersion();
browserInit(options);
browserInit(opts);
}

function checkAndSetAngularVersion(): void {
Expand Down
32 changes: 17 additions & 15 deletions packages/angular/src/sdk.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { VERSION } from '@angular/core';
import type { BrowserOptions } from '@sentry/browser';
import { defaultIntegrations, init as browserInit, SDK_VERSION, setContext } from '@sentry/browser';
import type { SdkMetadata } from '@sentry/types';
import { logger } from '@sentry/utils';

import { IS_DEBUG_BUILD } from './flags';
Expand All @@ -9,8 +10,21 @@ import { IS_DEBUG_BUILD } from './flags';
* Inits the Angular SDK
*/
export function init(options: BrowserOptions): void {
options._metadata = options._metadata || {};
options._metadata.sdk = {
const opts = {
_metadata: {} as SdkMetadata,
// Filter out TryCatch integration as it interferes with our Angular `ErrorHandler`:
// TryCatch would catch certain errors before they reach the `ErrorHandler` and thus provide a
// lower fidelity error than what `SentryErrorHandler` (see errorhandler.ts) would provide.
// see:
// - https://github.com/getsentry/sentry-javascript/issues/5417#issuecomment-1453407097
// - https://github.com/getsentry/sentry-javascript/issues/2744
defaultIntegrations: defaultIntegrations.filter(integration => {
return integration.name !== 'TryCatch';
}),
...options,
};

opts._metadata.sdk = opts._metadata.sdk || {
name: 'sentry.javascript.angular',
packages: [
{
Expand All @@ -21,20 +35,8 @@ export function init(options: BrowserOptions): void {
version: SDK_VERSION,
};

// Filter out TryCatch integration as it interferes with our Angular `ErrorHandler`:
// TryCatch would catch certain errors before they reach the `ErrorHandler` and thus provide a
// lower fidelity error than what `SentryErrorHandler` (see errorhandler.ts) would provide.
// see:
// - https://github.com/getsentry/sentry-javascript/issues/5417#issuecomment-1453407097
// - https://github.com/getsentry/sentry-javascript/issues/2744
if (options.defaultIntegrations === undefined) {
options.defaultIntegrations = defaultIntegrations.filter(integration => {
return integration.name !== 'TryCatch';
});
}

checkAndSetAngularVersion();
browserInit(options);
browserInit(opts);
}

function checkAndSetAngularVersion(): void {
Expand Down
13 changes: 8 additions & 5 deletions packages/nextjs/src/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,17 @@ const globalWithInjectedValues = global as typeof global & {

/** Inits the Sentry NextJS SDK on the browser with the React SDK. */
export function init(options: BrowserOptions): void {
applyTunnelRouteOption(options);
buildMetadata(options, ['nextjs', 'react']);
const opts = {
environment: getVercelEnv(true) || process.env.NODE_ENV,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, @mydea !
Maybe I don't fully understand how it's supposed to work, but this breaks our app on update, cause we used to pass environment in options in sentry.client.config.ts, and now it seems to be ignored? It falls back to getVercelEnv in our case, which calls process, which doesn't exist in browser. I am not sure if it's a cause or maybe we're using it wrong and this code should never reach client?

We're getting Uncaught ReferenceError: process is not defined here:
image

Downgrading to 7.73.0, before this change, fixes it for us.
Any advise?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We object spread in the options, so an explicitly set environment should override what the sdk attempts to set.

const opts = {
  environment: getVercelEnv(true) || process.env.NODE_ENV,
  // environment defined on passed in options should override above
  ...options
}

Could you please open a GH issue with a minimal reproduction so we can help debug further? Thanks!

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it does override it potentially, but it fails before cause process doesn't exist in client. I am on the go now, will try to create an issue later. Thank you!

...options,
};

options.environment = options.environment || getVercelEnv(true) || process.env.NODE_ENV;
applyTunnelRouteOption(opts);
buildMetadata(opts, ['nextjs', 'react']);

addClientIntegrations(options);
addClientIntegrations(opts);

reactInit(options);
reactInit(opts);

configureScope(scope => {
scope.setTag('runtime', 'browser');
Expand Down
11 changes: 8 additions & 3 deletions packages/nextjs/src/edge/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { SDK_VERSION } from '@sentry/core';
import type { SdkMetadata } from '@sentry/types';
import type { VercelEdgeOptions } from '@sentry/vercel-edge';
import { init as vercelEdgeInit } from '@sentry/vercel-edge';

export type EdgeOptions = VercelEdgeOptions;

/** Inits the Sentry NextJS SDK on the Edge Runtime. */
export function init(options: VercelEdgeOptions = {}): void {
options._metadata = options._metadata || {};
options._metadata.sdk = options._metadata.sdk || {
const opts = {
_metadata: {} as SdkMetadata,
...options,
};

opts._metadata.sdk = opts._metadata.sdk || {
name: 'sentry.javascript.nextjs',
packages: [
{
Expand All @@ -18,7 +23,7 @@ export function init(options: VercelEdgeOptions = {}): void {
version: SDK_VERSION,
};

vercelEdgeInit(options);
vercelEdgeInit(opts);
}

/**
Expand Down
20 changes: 11 additions & 9 deletions packages/nextjs/src/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,14 @@ const IS_VERCEL = !!process.env.VERCEL;

/** Inits the Sentry NextJS SDK on node. */
export function init(options: NodeOptions): void {
if (__DEBUG_BUILD__ && options.debug) {
const opts = {
environment: process.env.SENTRY_ENVIRONMENT || getVercelEnv(false) || process.env.NODE_ENV,
...options,
// Right now we only capture frontend sessions for Next.js
autoSessionTracking: false,
};

if (__DEBUG_BUILD__ && opts.debug) {
logger.enable();
}

Expand All @@ -75,16 +82,11 @@ export function init(options: NodeOptions): void {
return;
}

buildMetadata(options, ['nextjs', 'node']);

options.environment =
options.environment || process.env.SENTRY_ENVIRONMENT || getVercelEnv(false) || process.env.NODE_ENV;
buildMetadata(opts, ['nextjs', 'node']);

addServerIntegrations(options);
// Right now we only capture frontend sessions for Next.js
options.autoSessionTracking = false;
addServerIntegrations(opts);

nodeInit(options);
nodeInit(opts);

const filterTransactions: EventProcessor = event => {
return event.type === 'transaction' && event.transaction === '/404' ? null : event;
Expand Down
11 changes: 8 additions & 3 deletions packages/react/src/sdk.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import type { BrowserOptions } from '@sentry/browser';
import { init as browserInit, SDK_VERSION } from '@sentry/browser';
import type { SdkMetadata } from '@sentry/types';

/**
* Inits the React SDK
*/
export function init(options: BrowserOptions): void {
options._metadata = options._metadata || {};
options._metadata.sdk = options._metadata.sdk || {
const opts = {
_metadata: {} as SdkMetadata,
...options,
};

opts._metadata.sdk = opts._metadata.sdk || {
name: 'sentry.javascript.react',
packages: [
{
Expand All @@ -16,5 +21,5 @@ export function init(options: BrowserOptions): void {
],
version: SDK_VERSION,
};
browserInit(options);
browserInit(opts);
}
15 changes: 8 additions & 7 deletions packages/serverless/src/awslambda.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import type { Scope } from '@sentry/node';
import * as Sentry from '@sentry/node';
import { captureException, captureMessage, flush, getCurrentHub, withScope } from '@sentry/node';
import type { Integration } from '@sentry/types';
import type { Integration, SdkMetadata } from '@sentry/types';
import { isString, logger, tracingContextFromHeaders } from '@sentry/utils';
// NOTE: I have no idea how to fix this right now, and don't want to waste more time, as it builds just fine — Kamil
// eslint-disable-next-line import/no-unresolved
Expand Down Expand Up @@ -61,12 +61,13 @@ interface AWSLambdaOptions extends Sentry.NodeOptions {
* @see {@link Sentry.init}
*/
export function init(options: AWSLambdaOptions = {}): void {
if (options.defaultIntegrations === undefined) {
options.defaultIntegrations = defaultIntegrations;
}
const opts = {
_metadata: {} as SdkMetadata,
defaultIntegrations,
...options,
};

options._metadata = options._metadata || {};
options._metadata.sdk = {
opts._metadata.sdk = opts._metadata.sdk || {
name: 'sentry.javascript.serverless',
integrations: ['AWSLambda'],
packages: [
Expand All @@ -78,7 +79,7 @@ export function init(options: AWSLambdaOptions = {}): void {
version: Sentry.SDK_VERSION,
};

Sentry.init(options);
Sentry.init(opts);
Sentry.addGlobalEventProcessor(serverlessEventProcessor);
}

Expand Down
15 changes: 8 additions & 7 deletions packages/serverless/src/gcpfunction/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as Sentry from '@sentry/node';
import type { Integration } from '@sentry/types';
import type { Integration, SdkMetadata } from '@sentry/types';

import { GoogleCloudGrpc } from '../google-cloud-grpc';
import { GoogleCloudHttp } from '../google-cloud-http';
Expand All @@ -19,12 +19,13 @@ export const defaultIntegrations: Integration[] = [
* @see {@link Sentry.init}
*/
export function init(options: Sentry.NodeOptions = {}): void {
if (options.defaultIntegrations === undefined) {
options.defaultIntegrations = defaultIntegrations;
}
const opts = {
_metadata: {} as SdkMetadata,
defaultIntegrations,
...options,
};

options._metadata = options._metadata || {};
options._metadata.sdk = {
opts._metadata.sdk = opts._metadata.sdk || {
name: 'sentry.javascript.serverless',
integrations: ['GCPFunction'],
packages: [
Expand All @@ -36,6 +37,6 @@ export function init(options: Sentry.NodeOptions = {}): void {
version: Sentry.SDK_VERSION,
};

Sentry.init(options);
Sentry.init(opts);
Sentry.addGlobalEventProcessor(serverlessEventProcessor);
}
13 changes: 8 additions & 5 deletions packages/svelte/src/sdk.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import type { BrowserOptions } from '@sentry/browser';
import { addGlobalEventProcessor, init as browserInit, SDK_VERSION } from '@sentry/browser';
import type { EventProcessor } from '@sentry/types';
import type { EventProcessor, SdkMetadata } from '@sentry/types';
import { getDomElement } from '@sentry/utils';
/**
* Inits the Svelte SDK
*/
export function init(options: BrowserOptions): void {
options._metadata = options._metadata || {};
options._metadata.sdk = options._metadata.sdk || {
const opts = {
_metadata: {} as SdkMetadata,
...options,
};

opts._metadata.sdk = opts._metadata.sdk || {
name: 'sentry.javascript.svelte',
packages: [
{
Expand All @@ -17,8 +21,7 @@ export function init(options: BrowserOptions): void {
],
version: SDK_VERSION,
};

browserInit(options);
browserInit(opts);

detectAndReportSvelteKit();
}
Expand Down