Skip to content

feat(tracing): Expose BrowserTracing in non-tracing bundles #7479

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 4 commits into from
Mar 20, 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
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@
"karma-firefox-launcher": "^1.1.0",
"lerna": "6.5.0-alpha.2",
"madge": "4.0.2",
"magic-string": "^0.27.0",
"mocha": "^6.1.4",
"nodemon": "^2.0.16",
"npm-run-all": "^4.1.5",
Expand All @@ -108,7 +107,6 @@
"rollup": "^2.67.1",
"rollup-plugin-cleanup": "3.2.1",
"rollup-plugin-license": "^2.6.1",
"rollup-plugin-modify": "^3.0.0",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-typescript2": "^0.31.2",
"sinon": "^7.3.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ sentryTest(
await forceFlushReplay();

expect(requestCount).toBe(0);
expect(consoleMessages).toEqual([
'You are using new Replay() even though this bundle does not include the replay integration.',
]);
expect(consoleMessages).toEqual(['You are using new Replay() even though this bundle does not include replay.']);
},
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import * as Sentry from '@sentry/browser';

window.Sentry = Sentry;

Sentry.init({
dsn: 'https://[email protected]/1337',
sampleRate: 1,
integrations: [new Sentry.Integrations.BrowserTracing()],
});

// This should not fail
Sentry.addTracingExtensions();
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<button onclick="console.log('Test log')">Click me</button>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { expect } from '@playwright/test';

import { sentryTest } from '../../../utils/fixtures';

sentryTest(
'exports a shim Integrations.BrowserTracing integration for non-tracing bundles',
async ({ getLocalTestPath, page }) => {
const bundle = process.env.PW_BUNDLE;
const tracingOnly = Boolean(process.env.PW_TRACING_ONLY);

if (!bundle || !bundle.startsWith('bundle_') || tracingOnly) {
sentryTest.skip();
}

const consoleMessages: string[] = [];
page.on('console', msg => consoleMessages.push(msg.text()));

let requestCount = 0;
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
requestCount++;
return route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ id: 'test-id' }),
});
});

const url = await getLocalTestPath({ testDir: __dirname });

await page.goto(url);

expect(requestCount).toBe(0);
expect(consoleMessages).toEqual([
'You are using new BrowserTracing() even though this bundle does not include tracing.',
]);
},
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import * as Sentry from '@sentry/browser';

window.Sentry = Sentry;

Sentry.init({
dsn: 'https://[email protected]/1337',
sampleRate: 1,
integrations: [new Sentry.BrowserTracing()],
});

// This should not fail
Sentry.addTracingExtensions();
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<button onclick="console.log('Test log')">Click me</button>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { expect } from '@playwright/test';

import { sentryTest } from '../../../utils/fixtures';

sentryTest('exports a shim BrowserTracing integration for non-tracing bundles', async ({ getLocalTestPath, page }) => {
const bundle = process.env.PW_BUNDLE;
const tracingOnly = Boolean(process.env.PW_TRACING_ONLY);

if (!bundle || !bundle.startsWith('bundle_') || tracingOnly) {
sentryTest.skip();
}

const consoleMessages: string[] = [];
page.on('console', msg => consoleMessages.push(msg.text()));

let requestCount = 0;
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
requestCount++;
return route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ id: 'test-id' }),
});
});

const url = await getLocalTestPath({ testDir: __dirname });

await page.goto(url);

expect(requestCount).toBe(0);
expect(consoleMessages).toEqual([
'You are using new BrowserTracing() even though this bundle does not include tracing.',
]);
});
6 changes: 2 additions & 4 deletions packages/browser/rollup.bundle.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ const builds = [];
['es5', 'es6'].forEach(jsVersion => {
const baseBundleConfig = makeBaseBundleConfig({
bundleType: 'standalone',
entrypoints: ['src/index.ts'],
entrypoints: ['src/index.bundle.ts'],
jsVersion,
licenseTitle: '@sentry/browser',
includeReplay: 'shim',
outputFileBase: () => `bundles/bundle${jsVersion === 'es5' ? '.es5' : ''}`,
});

Expand All @@ -18,11 +17,10 @@ const builds = [];
// Full bundle incl. replay only available for es6
const replayBaseBundleConfig = makeBaseBundleConfig({
bundleType: 'standalone',
entrypoints: ['src/index.ts'],
entrypoints: ['src/index.bundle.replay.ts'],
jsVersion: 'es6',
licenseTitle: '@sentry/browser & @sentry/replay',
outputFileBase: () => 'bundles/bundle.replay',
includeReplay: true,
});

builds.push(...makeBundleConfigVariants(replayBaseBundleConfig));
Expand Down
23 changes: 23 additions & 0 deletions packages/browser/src/index.bundle.base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export * from './exports';

import { Integrations as CoreIntegrations } from '@sentry/core';
import type { Integration } from '@sentry/types';

import { WINDOW } from './helpers';
import * as BrowserIntegrations from './integrations';

let windowIntegrations = {};

// This block is needed to add compatibility with the integrations packages when used with a CDN
if (WINDOW.Sentry && WINDOW.Sentry.Integrations) {
windowIntegrations = WINDOW.Sentry.Integrations;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const INTEGRATIONS: Record<string, new (...args: any[]) => Integration> = {
...windowIntegrations,
...CoreIntegrations,
...BrowserIntegrations,
};

export { INTEGRATIONS as Integrations };
13 changes: 13 additions & 0 deletions packages/browser/src/index.bundle.replay.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// This is exported so the loader does not fail when switching off Replay/Tracing
import { addTracingExtensions, BrowserTracing } from '@sentry-internal/integration-shims';
import { Replay } from '@sentry/replay';

import * as Sentry from './index.bundle.base';

// TODO (v8): Remove this as it was only needed for backwards compatibility
Sentry.Integrations.Replay = Replay;

Sentry.Integrations.BrowserTracing = BrowserTracing;

export * from './index.bundle.base';
export { BrowserTracing, addTracingExtensions, Replay };
12 changes: 12 additions & 0 deletions packages/browser/src/index.bundle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// This is exported so the loader does not fail when switching off Replay/Tracing
import { addTracingExtensions, BrowserTracing, Replay } from '@sentry-internal/integration-shims';

import * as Sentry from './index.bundle.base';

// TODO (v8): Remove this as it was only needed for backwards compatibility
Sentry.Integrations.Replay = Replay;

Sentry.Integrations.BrowserTracing = BrowserTracing;

export * from './index.bundle.base';
export { BrowserTracing, addTracingExtensions, Replay };
16 changes: 0 additions & 16 deletions packages/browser/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,9 @@ const INTEGRATIONS = {

export { INTEGRATIONS as Integrations };

// DO NOT DELETE THESE COMMENTS!
// We want to exclude Replay/Offline from CDN bundles, so we remove the block below with our
// makeExcludeBlockPlugin Rollup plugin when generating bundles. Everything between
// ROLLUP_EXCLUDE_*_FROM_BUNDLES_BEGIN and _END__ is removed for bundles.

// __ROLLUP_EXCLUDE_REPLAY_FROM_BUNDLES_BEGIN__
export { Replay } from '@sentry/replay';
// __ROLLUP_EXCLUDE_REPLAY_FROM_BUNDLES_END__

// __ROLLUP_EXCLUDE_BROWSER_TRACING_FROM_BUNDLES_BEGIN__
export { BrowserTracing } from '@sentry-internal/tracing';
export { addTracingExtensions } from '@sentry/core';
// __ROLLUP_EXCLUDE_BROWSER_TRACING_FROM_BUNDLES_END__

// __ROLLUP_EXCLUDE_OFFLINE_FROM_BUNDLES_BEGIN__
export { makeBrowserOfflineTransport } from './transports/offline';
// __ROLLUP_EXCLUDE_OFFLINE_FROM_BUNDLES_END__

// __ROLLUP_EXCLUDE_BROWSER_PROFILING_FROM_BUNDLES_BEGIN__
export { onProfilingStartRouteTransaction } from './profiling/hubextensions';
export { BrowserProfilingIntegration } from './profiling/integration';
// __ROLLUP_EXCLUDE_BROWSER_PROFILING_FROM_BUNDLES_END__
23 changes: 23 additions & 0 deletions packages/browser/test/unit/index.bundle.replay.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { BrowserTracing as BrowserTracingShim } from '@sentry-internal/integration-shims';
import { Replay } from '@sentry/browser';

import * as TracingReplayBundle from '../../src/index.bundle.replay';

describe('index.bundle.replay', () => {
it('has correct exports', () => {
Object.keys(TracingReplayBundle.Integrations).forEach(key => {
// Skip BrowserTracing because it doesn't have a static id field.
if (key === 'BrowserTracing') {
return;
}

expect((TracingReplayBundle.Integrations[key] as any).id).toStrictEqual(expect.any(String));
});

expect(TracingReplayBundle.Integrations.Replay).toBe(Replay);
expect(TracingReplayBundle.Replay).toBe(Replay);

expect(TracingReplayBundle.Integrations.BrowserTracing).toBe(BrowserTracingShim);
expect(TracingReplayBundle.BrowserTracing).toBe(BrowserTracingShim);
});
});
22 changes: 22 additions & 0 deletions packages/browser/test/unit/index.bundle.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { BrowserTracing as BrowserTracingShim, Replay as ReplayShim } from '@sentry-internal/integration-shims';

import * as TracingBundle from '../../src/index.bundle';

describe('index.bundle', () => {
it('has correct exports', () => {
Object.keys(TracingBundle.Integrations).forEach(key => {
// Skip BrowserTracing because it doesn't have a static id field.
if (key === 'BrowserTracing') {
return;
}

expect((TracingBundle.Integrations[key] as any).id).toStrictEqual(expect.any(String));
});

expect(TracingBundle.Integrations.Replay).toBe(ReplayShim);
expect(TracingBundle.Replay).toBe(ReplayShim);

expect(TracingBundle.Integrations.BrowserTracing).toBe(BrowserTracingShim);
expect(TracingBundle.BrowserTracing).toBe(BrowserTracingShim);
});
});
36 changes: 36 additions & 0 deletions packages/integration-shims/src/BrowserTracing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { Integration } from '@sentry/types';

/**
* This is a shim for the BrowserTracing integration.
* It is needed in order for the CDN bundles to continue working when users add/remove tracing
* from it, without changing their config. This is necessary for the loader mechanism.
*/
class BrowserTracingShim implements Integration {
/**
* @inheritDoc
*/
public static id: string = 'BrowserTracing';

/**
* @inheritDoc
*/
public name: string = BrowserTracingShim.id;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
public constructor(_options: any) {
// eslint-disable-next-line no-console
console.error('You are using new BrowserTracing() even though this bundle does not include tracing.');
}

/** jsdoc */
public setupOnce(): void {
// noop
}
}

export { BrowserTracingShim as BrowserTracing };

/** Shim function */
export function addTracingExtensions(): void {
// noop
}
2 changes: 1 addition & 1 deletion packages/integration-shims/src/Replay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class ReplayShim implements Integration {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public constructor(_options: any) {
// eslint-disable-next-line no-console
console.error('You are using new Replay() even though this bundle does not include the replay integration.');
console.error('You are using new Replay() even though this bundle does not include replay.');
}

/** jsdoc */
Expand Down
3 changes: 2 additions & 1 deletion packages/integration-shims/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './Replay';
export { Replay } from './Replay';
export { BrowserTracing, addTracingExtensions } from './BrowserTracing';
2 changes: 0 additions & 2 deletions packages/tracing/rollup.bundle.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ const builds = [];
entrypoints: ['src/index.bundle.ts'],
jsVersion,
licenseTitle: '@sentry/tracing & @sentry/browser',
includeReplay: false,
outputFileBase: () => `bundles/bundle.tracing${jsVersion === 'es5' ? '.es5' : ''}`,
});

Expand All @@ -22,7 +21,6 @@ const replayBaseBundleConfig = makeBaseBundleConfig({
jsVersion: 'es6',
licenseTitle: '@sentry/tracing & @sentry/browser & @sentry/replay',
outputFileBase: () => 'bundles/bundle.tracing.replay',
includeReplay: true,
});

builds.push(...makeBundleConfigVariants(replayBaseBundleConfig));
Expand Down
7 changes: 2 additions & 5 deletions packages/tracing/src/index.bundle.base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,8 @@ if (GLOBAL_OBJ.Sentry && GLOBAL_OBJ.Sentry.Integrations) {
windowIntegrations = GLOBAL_OBJ.Sentry.Integrations;
}

// For whatever reason, it does not recognize BrowserTracing or some of the BrowserIntegrations as Integration
const INTEGRATIONS: Record<
string,
Integration | typeof BrowserTracing | typeof BrowserIntegrations[keyof typeof BrowserIntegrations]
> = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const INTEGRATIONS: Record<string, new (...args: any[]) => Integration> = {
...windowIntegrations,
...BrowserIntegrations,
BrowserTracing,
Expand Down
3 changes: 1 addition & 2 deletions packages/tracing/src/index.bundle.replay.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { Replay } from '@sentry/browser';

import * as Sentry from './index.bundle';
import * as Sentry from './index.bundle.base';

// TODO (v8): Remove this as it was only needed for backwards compatibility
// We want replay to be available under Sentry.Replay, to be consistent
// with the NPM package version.
Sentry.Integrations.Replay = Replay;

export { Replay };

export * from './index.bundle.base';
Loading