Skip to content

Commit 4a8597e

Browse files
committed
fix(ember): Ensure only one client is created
With the new `addIntegration` API, we don't need to create multiple clients anymore, which also potentially broke replays.
1 parent b5952df commit 4a8597e

File tree

8 files changed

+86
-51
lines changed

8 files changed

+86
-51
lines changed

packages/ember/addon/instance-initializers/sentry-performance.ts

Lines changed: 46 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -390,57 +390,56 @@ export async function instrumentForPerformance(appInstance: ApplicationInstance)
390390

391391
const idleTimeout = config.transitionTimeout || 5000;
392392

393-
const existingIntegrations = (sentryConfig['integrations'] || []) as Integration[];
394-
395-
sentryConfig['integrations'] = [
396-
...existingIntegrations,
397-
new BrowserTracing({
398-
routingInstrumentation: (customStartTransaction, startTransactionOnPageLoad) => {
399-
const routerMain = appInstance.lookup('router:main');
400-
let routerService = appInstance.lookup('service:router') as
401-
| RouterService & { externalRouter?: RouterService; _hasMountedSentryPerformanceRouting?: boolean };
402-
403-
if (routerService.externalRouter) {
404-
// Using ember-engines-router-service in an engine.
405-
routerService = routerService.externalRouter;
406-
}
407-
if (routerService._hasMountedSentryPerformanceRouting) {
408-
// Routing listens to route changes on the main router, and should not be initialized multiple times per page.
409-
return;
410-
}
411-
if (!routerService.recognize) {
412-
// Router is missing critical functionality to limit cardinality of the transaction names.
413-
return;
414-
}
415-
routerService._hasMountedSentryPerformanceRouting = true;
416-
_instrumentEmberRouter(routerService, routerMain, config, customStartTransaction, startTransactionOnPageLoad);
417-
},
418-
idleTimeout,
419-
...browserTracingOptions,
420-
}),
421-
];
422-
423-
class FakeBrowserTracingClass {
424-
static id = 'BrowserTracing';
425-
public name = FakeBrowserTracingClass.id;
426-
setupOnce() {
427-
// noop - We're just faking this class for a lookup
393+
const browserTracing = new BrowserTracing({
394+
routingInstrumentation: (customStartTransaction, startTransactionOnPageLoad) => {
395+
const routerMain = appInstance.lookup('router:main');
396+
let routerService = appInstance.lookup('service:router') as
397+
| RouterService & { externalRouter?: RouterService; _hasMountedSentryPerformanceRouting?: boolean };
398+
399+
if (routerService.externalRouter) {
400+
// Using ember-engines-router-service in an engine.
401+
routerService = routerService.externalRouter;
402+
}
403+
if (routerService._hasMountedSentryPerformanceRouting) {
404+
// Routing listens to route changes on the main router, and should not be initialized multiple times per page.
405+
return;
406+
}
407+
if (!routerService.recognize) {
408+
// Router is missing critical functionality to limit cardinality of the transaction names.
409+
return;
410+
}
411+
routerService._hasMountedSentryPerformanceRouting = true;
412+
_instrumentEmberRouter(routerService, routerMain, config, customStartTransaction, startTransactionOnPageLoad);
413+
},
414+
idleTimeout,
415+
...browserTracingOptions,
416+
});
417+
418+
if (macroCondition(isTesting())) {
419+
class FakeBrowserTracingClass {
420+
static id = 'BrowserTracing';
421+
public name = FakeBrowserTracingClass.id;
422+
setupOnce() {
423+
// noop - We're just faking this class for a lookup
424+
}
428425
}
429-
}
430426

431-
if (
432-
isTesting() &&
433-
Sentry.getCurrentHub()?.getIntegration(
434-
// This is a temporary hack because the BrowserTracing integration cannot have a static `id` field for tree
435-
// shaking reasons. However, `getIntegration` needs that field.
436-
FakeBrowserTracingClass,
437-
)
438-
) {
439-
// Initializers are called more than once in tests, causing the integrations to not be setup correctly.
440-
return;
427+
if (
428+
Sentry.getCurrentHub()?.getIntegration(
429+
// This is a temporary hack because the BrowserTracing integration cannot have a static `id` field for tree
430+
// shaking reasons. However, `getIntegration` needs that field.
431+
FakeBrowserTracingClass,
432+
)
433+
) {
434+
// Initializers are called more than once in tests, causing the integrations to not be setup correctly.
435+
return;
436+
}
441437
}
442438

443-
Sentry.init(sentryConfig); // Call init again to rebind client with new integration list in addition to the defaults
439+
const client = Sentry.getCurrentHub().getClient();
440+
if (client && client.addIntegration) {
441+
client.addIntegration(browserTracing);
442+
}
444443

445444
_instrumentEmberRunloop(config);
446445
_instrumentComponents(config);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { test, module } from 'qunit';
2+
import { setupApplicationTest } from 'ember-qunit';
3+
import { visit } from '@ember/test-helpers';
4+
import { setupSentryTest } from '../helpers/setup-sentry';
5+
import * as Sentry from '@sentry/ember';
6+
7+
module('Acceptance | Sentry Session Replay', function (hooks) {
8+
setupApplicationTest(hooks);
9+
setupSentryTest(hooks);
10+
11+
test('Test replay', async function (assert) {
12+
await visit('/replay');
13+
14+
const replay = Sentry.getCurrentHub().getIntegration(Sentry.Replay);
15+
assert.ok(replay);
16+
17+
assert.true(replay._replay.isEnabled());
18+
assert.false(replay._replay.isPaused());
19+
});
20+
});

packages/ember/tests/dummy/app/app.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import config from './config/environment';
55
import * as Sentry from '@sentry/ember';
66

77
Sentry.init({
8+
replaysSessionSampleRate: 1,
9+
replaysOnErrorSampleRate: 1,
810
browserTracingOptions: {
911
_experiments: {
1012
// This lead to some flaky tests, as that is sometimes logged

packages/ember/tests/dummy/app/router.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export default class Router extends EmberRouter {
88

99
Router.map(function () {
1010
this.route('tracing');
11+
this.route('replay');
1112
this.route('slow-loading-route', function () {
1213
this.route('index', { path: '/' });
1314
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import Route from '@ember/routing/route';
2+
import * as Sentry from '@sentry/ember';
3+
4+
export default class ReplayRoute extends Route {
5+
async beforeModel() {
6+
const { Replay } = Sentry;
7+
8+
if (!Sentry.getCurrentHub().getIntegration(Replay)) {
9+
const client = Sentry.getCurrentHub().getClient();
10+
client.addIntegration(new Replay());
11+
}
12+
}
13+
}

packages/ember/tests/dummy/app/templates/application.hbs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<div class="nav">
1212
<Link @route='index'>Errors</Link>
1313
<Link @route='tracing'>Tracing</Link>
14+
<Link @route='replay'>Replay</Link>
1415
</div>
1516
<div class="content-container">
1617
{{outlet}}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h2>Visiting this page starts Replay!</h2>

packages/ember/tests/dummy/config/environment.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ module.exports = function (environment) {
2222
ENV['@sentry/ember'] = {
2323
sentry: {
2424
tracesSampleRate: 1,
25-
dsn: process.env.SENTRY_DSN,
25+
// Include fake dsn so that instrumentation is enabled when running from cli
26+
dsn: process.env.SENTRY_DSN || 'https://[email protected]/0',
2627
browserTracingOptions: {
2728
tracingOrigins: ['localhost', 'doesntexist.example'],
2829
},
@@ -50,9 +51,6 @@ module.exports = function (environment) {
5051

5152
ENV.APP.rootElement = '#ember-testing';
5253
ENV.APP.autoboot = false;
53-
54-
// Include fake dsn so that instrumentation is enabled when running from cli
55-
ENV['@sentry/ember'].sentry.dsn = 'https://[email protected]/0';
5654
}
5755

5856
if (environment === 'production') {

0 commit comments

Comments
 (0)