Skip to content
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
6 changes: 6 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -1156,6 +1156,8 @@ Note that v10.30.0 deprecated a top-level `reactComponentAnnotation` in favour o

On Turbopack, component annotation requires Next.js 16+. The SDK now warns at build time if annotation is enabled on an older Next.js version, where it previously did nothing silently.

**Default `environment` on Vercel no longer has a `vercel-` prefix:** On Vercel, the SDK now defaults `environment` to the value of `VERCEL_TARGET_ENV` (`production`, `preview`, or a custom environment name) instead of `vercel-production` / `vercel-preview`. Update alert rules, dashboards and saved searches that reference the old names, or keep them by setting `environment` explicitly.

**Vercel AI no longer supported on Edge runtime:** We now rely on diagnostics channels for our Vercel AI instrumentation, which does not work on the Edge runtime. Because of this, monitoring of the `ai` package is no longer supported on Edge. Note that Edge is deprecated.

### Cloudflare: `nodejs_compat` compatibility flag is now required
Expand Down Expand Up @@ -1689,6 +1691,10 @@ moved under the `webpack` option in v10; use the replacement listed below instea

The deprecated `sourceMapsUploadOptions` and other deprecated Vite/build plugin options were removed from `@sentry/astro`, `@sentry/nuxt` and `@sentry/sveltekit`. Use the top-level equivalents (e.g. `sourcemaps`, `release`, `authToken`, `org`, `project`, `telemetry`) instead.

### Bundler plugins: Vercel deploys use the plain Vercel environment name

Deploys that the bundler plugins create automatically on Vercel now use the value of `VERCEL_TARGET_ENV` (`production`, `preview`, or a custom environment name) as their environment instead of `vercel-production` / `vercel-preview`. This matches the new default runtime `environment` of `@sentry/nextjs`, and the `production` default of all other SDKs. If your events use a different environment, set `release.deploy.env` to the same value, or set `release.deploy` to `false` to opt out.

### Removed `unstable_` bundler plugin options

The `unstable_sentry*PluginOptions` escape hatch was removed from every SDK. It existed because the Sentry
Expand Down
6 changes: 4 additions & 2 deletions packages/bundler-plugins/src/core/options-mapping.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getVercelEnv } from '@sentry/core';
import type { Logger } from './logger';
import type {
Options as UserOptions,
Expand Down Expand Up @@ -162,9 +163,10 @@ export function normalizeUserOptions(userOptions: UserOptions): NormalizedOption
}
}

if (options.release.deploy === undefined && process.env['VERCEL'] && process.env['VERCEL_TARGET_ENV']) {
const vercelEnv = getVercelEnv();
if (options.release.deploy === undefined && process.env['VERCEL'] && vercelEnv) {
options.release.deploy = {
env: `vercel-${process.env['VERCEL_TARGET_ENV']}`,
env: vercelEnv,
url: process.env['VERCEL_URL'] ? `https://${process.env['VERCEL_URL']}` : undefined,
};
}
Expand Down
2 changes: 1 addition & 1 deletion packages/bundler-plugins/test/core/option-mappings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ describe('normalizeUserOptions()', () => {
const normalizedOptions = normalizeUserOptions(userOptions);

expect(normalizedOptions.release.deploy).toEqual({
env: 'vercel-production',
env: 'production',
url: 'https://my-app.vercel.app',
});
});
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export { filterCookies as _INTERNAL_filterCookies } from './utils/data-collectio
export { filterQueryParams as _INTERNAL_filterQueryParams } from './utils/data-collection/filterQueryParams';
export { filterCollectedUrl, filterCollectedUrlQuery } from './utils/data-collection/filterCollectedUrl';
export { envToBool } from './utils/envToBool';
export { getVercelEnv } from './utils/vercel';
export { applyScopeDataToEvent, mergeScopeData, getCombinedScopeData } from './utils/scopeData';
export { prepareEvent } from './utils/prepareEvent';
export type { ExclusiveEventHintOrCaptureContext } from './utils/prepareEvent';
Expand Down
15 changes: 15 additions & 0 deletions packages/core/src/utils/vercel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Returns the Vercel environment the code is running in, determined by the `VERCEL_TARGET_ENV` environment variable
* with `VERCEL_ENV` as fallback. Returns `undefined` outside of Vercel.
*
* `VERCEL_TARGET_ENV` also carries the name of custom Vercel environments, whereas `VERCEL_ENV` only ever holds
* `production`, `preview` or `development`. SDKs use this as the default `environment` and the bundler plugins use it
* for the deploys they create, so the two stay in sync and deploys show up next to events.
*/
export function getVercelEnv(): string | undefined {
if (typeof process === 'undefined') {
return undefined;
}

return process.env.VERCEL_TARGET_ENV || process.env.VERCEL_ENV || undefined;
}
33 changes: 33 additions & 0 deletions packages/core/test/lib/utils/vercel.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
import { getVercelEnv } from '../../../src/utils/vercel';

describe('getVercelEnv', () => {
const originalEnv = process.env;

beforeEach(() => {
process.env = { ...originalEnv };
delete process.env.VERCEL_ENV;
delete process.env.VERCEL_TARGET_ENV;
});

afterEach(() => {
process.env = originalEnv;
});

it('returns undefined when no Vercel env vars are set', () => {
expect(getVercelEnv()).toBeUndefined();
});

it('returns VERCEL_TARGET_ENV without a prefix', () => {
process.env.VERCEL_ENV = 'preview';
process.env.VERCEL_TARGET_ENV = 'staging';

expect(getVercelEnv()).toBe('staging');
});

it('falls back to VERCEL_ENV when VERCEL_TARGET_ENV is not set', () => {
process.env.VERCEL_ENV = 'production';

expect(getVercelEnv()).toBe('production');
});
});
4 changes: 2 additions & 2 deletions packages/nextjs/src/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { BrowserOptions } from '@sentry/react';
import { getDefaultIntegrations as getReactDefaultIntegrations, init as reactInit } from '@sentry/react';
import { DEBUG_BUILD } from '../common/debug-build';
import { devErrorSymbolicationEventProcessor } from '../common/devErrorSymbolicationEventProcessor';
import { getVercelEnv } from '../common/getVercelEnv';
import { getClientVercelEnv } from '../common/getVercelEnv';
import { isRedirectNavigationError } from '../common/nextNavigationErrorUtils';
import { browserTracingIntegration } from './browserTracingIntegration';
import { nextjsClientStackFrameNormalizationIntegration } from './clientNormalizationIntegration';
Expand Down Expand Up @@ -63,7 +63,7 @@ export function init(options: BrowserOptions): Client | undefined {
}

const opts = {
environment: options.environment || process.env.SENTRY_ENVIRONMENT || getVercelEnv(true) || process.env.NODE_ENV,
environment: options.environment || process.env.SENTRY_ENVIRONMENT || getClientVercelEnv() || process.env.NODE_ENV,
defaultIntegrations: getDefaultIntegrations(options),
release: process.env._sentryRelease || globalWithInjectedValues._sentryRelease,
...options,
Expand Down
10 changes: 4 additions & 6 deletions packages/nextjs/src/common/getVercelEnv.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/**
* Returns an environment setting value determined by Vercel's `VERCEL_ENV` environment variable.
*
* @param isClient Flag to indicate whether to use the `NEXT_PUBLIC_` prefixed version of the environment variable.
* Browser counterpart of `getVercelEnv` from `@sentry/core`, reading the `NEXT_PUBLIC_` variants that Next.js exposes
* to the client. The variables must be referenced statically so Next.js can inline them at build time.
*/
export function getVercelEnv(isClient: boolean): string | undefined {
const vercelEnvVar = isClient ? process.env.NEXT_PUBLIC_VERCEL_ENV : process.env.VERCEL_ENV;
return vercelEnvVar ? `vercel-${vercelEnvVar}` : undefined;
export function getClientVercelEnv(): string | undefined {
return process.env.NEXT_PUBLIC_VERCEL_TARGET_ENV || process.env.NEXT_PUBLIC_VERCEL_ENV || undefined;
}
13 changes: 10 additions & 3 deletions packages/nextjs/src/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,19 @@
/* eslint-disable import/export */
import { HTTP_TARGET, URL_QUERY } from '@sentry/conventions/attributes';
import type { EventProcessor } from '@sentry/core';
import { applySdkMetadata, debug, getClient, getGlobalScope, getRootSpan, GLOBAL_OBJ } from '@sentry/core';
import {
applySdkMetadata,
debug,
getClient,
getGlobalScope,
getRootSpan,
getVercelEnv,
GLOBAL_OBJ,
} from '@sentry/core';
import type { NodeClient, NodeOptions } from '@sentry/node';
import { getDefaultIntegrations, httpIntegration, init as nodeInit } from '@sentry/node';
import { DEBUG_BUILD } from '../common/debug-build';
import { devErrorSymbolicationEventProcessor } from '../common/devErrorSymbolicationEventProcessor';
import { getVercelEnv } from '../common/getVercelEnv';
import { isPrerenderControlFlowError } from '../common/nextNavigationErrorUtils';
import { TRANSACTION_ATTR_SHOULD_DROP_TRANSACTION } from '../common/span-attributes-with-logic-attached';
import { isBuild } from '../common/utils/isBuild';
Expand Down Expand Up @@ -138,7 +145,7 @@ export function init(options: NodeOptions): NodeClient | undefined {
const cloudflareConfig = getCloudflareRuntimeConfig();

const opts: NodeOptions = {
environment: options.environment || process.env.SENTRY_ENVIRONMENT || getVercelEnv(false) || process.env.NODE_ENV,
environment: options.environment || process.env.SENTRY_ENVIRONMENT || getVercelEnv() || process.env.NODE_ENV,
release: process.env._sentryRelease || globalWithInjectedValues._sentryRelease,
defaultIntegrations: customDefaultIntegrations,
// Next.js emits its own OpenTelemetry spans, so it defaults to registering the Sentry tracer
Expand Down
30 changes: 30 additions & 0 deletions packages/nextjs/test/common/getVercelEnv.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
import { getClientVercelEnv } from '../../src/common/getVercelEnv';

describe('getClientVercelEnv', () => {
const originalEnv = process.env;

beforeEach(() => {
process.env = { ...originalEnv };
delete process.env.NEXT_PUBLIC_VERCEL_ENV;
delete process.env.NEXT_PUBLIC_VERCEL_TARGET_ENV;
});

afterEach(() => {
process.env = originalEnv;
});

it('returns undefined when no Vercel env vars are set', () => {
expect(getClientVercelEnv()).toBeUndefined();
});

it('prefers NEXT_PUBLIC_VERCEL_TARGET_ENV over NEXT_PUBLIC_VERCEL_ENV', () => {
process.env.NEXT_PUBLIC_VERCEL_ENV = 'preview';
process.env.NEXT_PUBLIC_VERCEL_TARGET_ENV = 'staging';

expect(getClientVercelEnv()).toBe('staging');

delete process.env.NEXT_PUBLIC_VERCEL_TARGET_ENV;
expect(getClientVercelEnv()).toBe('preview');
});
});
5 changes: 2 additions & 3 deletions packages/vercel-edge/src/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
functionToStringIntegration,
getCurrentScope,
getIntegrationsToSetup,
getVercelEnv,
GLOBAL_OBJ,
linkedErrorsIntegration,
requestDataIntegration,
Expand All @@ -25,7 +26,6 @@ import { VercelEdgeClient } from './client';
import { winterCGFetchIntegration } from './integrations/wintercg-fetch';
import { makeEdgeTransport } from './transports';
import type { VercelEdgeOptions } from './types';
import { getVercelEnv } from './utils/vercel';

declare const process: {
env: Record<string, string>;
Expand Down Expand Up @@ -76,8 +76,7 @@ export function init(options: VercelEdgeOptions = {}): Client {
}
}

options.environment =
options.environment || process.env.SENTRY_ENVIRONMENT || getVercelEnv(false) || process.env.NODE_ENV;
options.environment = options.environment || process.env.SENTRY_ENVIRONMENT || getVercelEnv() || process.env.NODE_ENV;

options.traceLifecycle = options.traceLifecycle ?? getTraceLifecycleFromEnv(process.env.SENTRY_TRACE_LIFECYCLE);

Expand Down
13 changes: 0 additions & 13 deletions packages/vercel-edge/src/utils/vercel.ts

This file was deleted.

Loading