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
10 changes: 9 additions & 1 deletion instrumentation-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,15 @@ posthog.init(process.env.NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN!, {
debug: process.env.NODE_ENV === 'development',
});

const sentryOptions = buildSentryOptions('client');
// These must be written as literal `process.env.X` expressions: that is the
// only form Next substitutes when building the client bundle. Reading them
// dynamically leaves `undefined` in the browser and silently disables Sentry.
const sentryOptions = buildSentryOptions('client', {
NEXT_PUBLIC_SENTRY_DSN: process.env.NEXT_PUBLIC_SENTRY_DSN,
NODE_ENV: process.env.NODE_ENV,
SENTRY_ENVIRONMENT: process.env.NEXT_PUBLIC_SENTRY_ENVIRONMENT,
SENTRY_RELEASE: process.env.NEXT_PUBLIC_SENTRY_RELEASE,
});

Sentry.init({
enabled: sentryOptions.enabled,
Expand Down
28 changes: 28 additions & 0 deletions tests/observability/client-dsn-inlining.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { readFileSync } from 'node:fs';
import path from 'node:path';

import { describe, expect, test } from 'vitest';

/**
* Next only substitutes *literal* `process.env.NEXT_PUBLIC_*` references when
* it builds the client bundle. Reading the same name dynamically — say
* `env['NEXT_PUBLIC_SENTRY_DSN']` inside a helper — is left untouched, so the
* value is `undefined` in the browser and Sentry disables itself without any
* error. That shipped once already; these tests keep it from shipping again.
*/
describe('instrumentation-client.ts', () => {
const source = readFileSync(
path.resolve(__dirname, '../../instrumentation-client.ts'),
'utf8',
);

test('references the public DSN literally so the bundler can inline it', () => {
expect(source).toContain('process.env.NEXT_PUBLIC_SENTRY_DSN');
});

test('does not hand the raw process.env object to the options builder', () => {
// buildSentryOptions('client') with no second argument falls back to
// process.env, which is exactly the non-inlinable path.
expect(source).not.toMatch(/buildSentryOptions\(\s*'client'\s*\)/);
});
});
Loading