Skip to content

Commit 77a51bd

Browse files
authored
fix(ember/v7): Ensure unnecessary spans are avoided (#11848)
Backport of #11846
1 parent 217e4c1 commit 77a51bd

File tree

14 files changed

+118
-5
lines changed

14 files changed

+118
-5
lines changed

packages/ember/addon/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { getOwnConfig, isDevelopingApp, macroCondition } from '@embroider/macros
55
import { startSpan } from '@sentry/browser';
66
import type { BrowserOptions } from '@sentry/browser';
77
import * as Sentry from '@sentry/browser';
8-
import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, applySdkMetadata } from '@sentry/core';
8+
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, applySdkMetadata } from '@sentry/core';
99
import { GLOBAL_OBJ } from '@sentry/utils';
1010
import Ember from 'ember';
1111

@@ -83,10 +83,12 @@ export const instrumentRoutePerformance = <T extends RouteConstructor>(BaseRoute
8383
return startSpan(
8484
{
8585
attributes: {
86-
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'ember',
86+
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom',
87+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.ember',
8788
},
8889
op,
8990
name: description,
91+
onlyIfParent: true,
9092
},
9193
() => {
9294
return fn(...args);

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

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,12 @@ export function _instrumentEmberRouter(
155155

156156
routerService.on('routeWillChange', (transition: Transition) => {
157157
const { fromRoute, toRoute } = getTransitionInformation(transition, routerService);
158+
159+
// We want to ignore loading && error routes
160+
if (transitionIsIntermediate(transition)) {
161+
return;
162+
}
163+
158164
activeRootSpan?.end();
159165

160166
activeRootSpan = startBrowserTracingNavigationSpan(client, {
@@ -180,8 +186,8 @@ export function _instrumentEmberRouter(
180186
});
181187
});
182188

183-
routerService.on('routeDidChange', () => {
184-
if (!transitionSpan || !activeRootSpan) {
189+
routerService.on('routeDidChange', transition => {
190+
if (!transitionSpan || !activeRootSpan || transitionIsIntermediate(transition)) {
185191
return;
186192
}
187193
transitionSpan.end();
@@ -503,3 +509,18 @@ function _instrumentNavigation(
503509
export default {
504510
initialize,
505511
};
512+
513+
function transitionIsIntermediate(transition: Transition): boolean {
514+
// We want to use ignore, as this may actually be defined on new versions
515+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
516+
// @ts-ignore This actually exists on newer versions
517+
const isIntermediate: boolean | undefined = transition.isIntermediate;
518+
519+
if (typeof isIntermediate === 'boolean') {
520+
return isIntermediate;
521+
}
522+
523+
// For versions without this, we look if the route is a `.loading` or `.error` route
524+
// This is not perfect and may false-positive in some cases, but it's the best we can do
525+
return transition.to?.localName === 'loading' || transition.to?.localName === 'error';
526+
}

packages/ember/tests/acceptance/sentry-performance-test.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { click, visit } from '@ember/test-helpers';
1+
import { click, find, visit } from '@ember/test-helpers';
22
import { setupApplicationTest } from 'ember-qunit';
33
import { module, test } from 'qunit';
44

@@ -56,4 +56,45 @@ module('Acceptance | Sentry Performance', function (hooks) {
5656
},
5757
});
5858
});
59+
60+
test('Test page with loading state', async function (assert) {
61+
await visit('/with-loading');
62+
63+
assertSentryTransactionCount(assert, 1);
64+
assertSentryTransactions(assert, 0, {
65+
spans: [
66+
'ui.ember.transition | route:undefined -> route:with-loading.index',
67+
'ui.ember.route.before_model | with-loading.index',
68+
'ui.ember.route.model | with-loading.index',
69+
'ui.ember.route.after_model | with-loading.index',
70+
'ui.ember.route.setup_controller | with-loading.index',
71+
],
72+
transaction: 'route:with-loading.index',
73+
tags: {
74+
fromRoute: undefined,
75+
toRoute: 'with-loading.index',
76+
},
77+
});
78+
});
79+
80+
test('Test page with error state', async function (assert) {
81+
await visit('/with-error');
82+
83+
// Ensure we are on error page
84+
assert.ok(find('#test-page-load-error'));
85+
86+
assertSentryTransactionCount(assert, 1);
87+
assertSentryTransactions(assert, 0, {
88+
spans: [
89+
'ui.ember.transition | route:undefined -> route:with-error.index',
90+
'ui.ember.route.before_model | with-error.index',
91+
'ui.ember.route.model | with-error.index',
92+
],
93+
transaction: 'route:with-error.index',
94+
tags: {
95+
fromRoute: undefined,
96+
toRoute: 'with-error.index',
97+
},
98+
});
99+
});
59100
});

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,12 @@ Router.map(function () {
1515
this.route('slow-loading-route', function () {
1616
this.route('index', { path: '/' });
1717
});
18+
19+
this.route('with-loading', function () {
20+
this.route('index', { path: '/' });
21+
});
22+
23+
this.route('with-error', function () {
24+
this.route('index', { path: '/' });
25+
});
1826
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import Route from '@ember/routing/route';
2+
3+
export default class WithErrorErrorRoute extends Route {
4+
public model(): void {
5+
// Just swallow the error...
6+
}
7+
8+
public setupController() {
9+
// Just swallow the error...
10+
}
11+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import Route from '@ember/routing/route';
2+
import { instrumentRoutePerformance } from '@sentry/ember';
3+
4+
class WithErrorIndexRoute extends Route {
5+
public model(): Promise<void> {
6+
return Promise.reject('Test error');
7+
}
8+
}
9+
10+
export default instrumentRoutePerformance(WithErrorIndexRoute);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import Route from '@ember/routing/route';
2+
import { instrumentRoutePerformance } from '@sentry/ember';
3+
4+
import timeout from '../../helpers/utils';
5+
6+
class WithLoadingIndexRoute extends Route {
7+
public model(): Promise<void> {
8+
return timeout(1000);
9+
}
10+
}
11+
12+
export default instrumentRoutePerformance(WithLoadingIndexRoute);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
<Link @route='index'>Errors</Link>
1313
<Link @route='tracing'>Tracing</Link>
1414
<Link @route='replay'>Replay</Link>
15+
<Link @route='with-loading'>With Loading</Link>
16+
<Link @route='with-error'>With Error</Link>
1517
</div>
1618
<div class="content-container">
1719
{{outlet}}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{{outlet}}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<div id='test-page-load-error'>Error when loading the page!</div>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Page loaded!
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{{outlet}}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Page loaded!
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Loading page...

0 commit comments

Comments
 (0)