@sentry/ember 7.98.0 → 7.100.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/addon/index.ts CHANGED
@@ -5,7 +5,7 @@ import { getOwnConfig, isDevelopingApp, macroCondition } from '@embroider/macros
5
5
  import { startSpan } from '@sentry/browser';
6
6
  import type { BrowserOptions } from '@sentry/browser';
7
7
  import * as Sentry from '@sentry/browser';
8
- import { applySdkMetadata } from '@sentry/core';
8
+ import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, applySdkMetadata } from '@sentry/core';
9
9
  import { GLOBAL_OBJ } from '@sentry/utils';
10
10
  import Ember from 'ember';
11
11
 
@@ -82,9 +82,11 @@ export const instrumentRoutePerformance = <T extends RouteConstructor>(BaseRoute
82
82
  ): Promise<ReturnType<X>> => {
83
83
  return startSpan(
84
84
  {
85
+ attributes: {
86
+ [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'ember',
87
+ },
85
88
  op,
86
89
  name: description,
87
- origin: 'auto.ui.ember',
88
90
  },
89
91
  () => {
90
92
  return fn(...args);
@@ -8,17 +8,13 @@ import type { EmberRunQueues } from '@ember/runloop/-private/types';
8
8
  import { getOwnConfig, isTesting, macroCondition } from '@embroider/macros';
9
9
  import * as Sentry from '@sentry/browser';
10
10
  import type { ExtendedBackburner } from '@sentry/ember/runloop';
11
- import type { Span, Transaction } from '@sentry/types';
11
+ import type { Span } from '@sentry/types';
12
12
  import { GLOBAL_OBJ, browserPerformanceTimeOrigin, timestampInSeconds } from '@sentry/utils';
13
13
 
14
+ import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
14
15
  import type { BrowserClient } from '..';
15
16
  import { getActiveSpan, startInactiveSpan } from '..';
16
- import type { EmberRouterMain, EmberSentryConfig, GlobalConfig, OwnConfig, StartTransactionFunction } from '../types';
17
-
18
- type SentryTestRouterService = RouterService & {
19
- _startTransaction?: StartTransactionFunction;
20
- _sentryInstrumented?: boolean;
21
- };
17
+ import type { EmberRouterMain, EmberSentryConfig, GlobalConfig, OwnConfig } from '../types';
22
18
 
23
19
  function getSentryConfig(): EmberSentryConfig {
24
20
  const _global = GLOBAL_OBJ as typeof GLOBAL_OBJ & GlobalConfig;
@@ -97,26 +93,29 @@ export function _instrumentEmberRouter(
97
93
  routerService: RouterService,
98
94
  routerMain: EmberRouterMain,
99
95
  config: EmberSentryConfig,
100
- startTransaction: StartTransactionFunction,
101
- startTransactionOnPageLoad?: boolean,
102
- ): {
103
- startTransaction: StartTransactionFunction;
104
- } {
96
+ ): void {
105
97
  const { disableRunloopPerformance } = config;
106
98
  const location = routerMain.location;
107
- let activeTransaction: Transaction | undefined;
99
+ let activeRootSpan: Span | undefined;
108
100
  let transitionSpan: Span | undefined;
109
101
 
102
+ // Maintaining backwards compatibility with config.browserTracingOptions, but passing it with Sentry options is preferred.
103
+ const browserTracingOptions = config.browserTracingOptions || config.sentry.browserTracingOptions || {};
110
104
  const url = getLocationURL(location);
111
105
 
112
- if (macroCondition(isTesting())) {
113
- (routerService as SentryTestRouterService)._sentryInstrumented = true;
114
- (routerService as SentryTestRouterService)._startTransaction = startTransaction;
106
+ const client = Sentry.getClient<BrowserClient>();
107
+
108
+ if (!client) {
109
+ return;
115
110
  }
116
111
 
117
- if (startTransactionOnPageLoad && url) {
112
+ if (
113
+ url &&
114
+ browserTracingOptions.startTransactionOnPageLoad !== false &&
115
+ browserTracingOptions.instrumentPageLoad !== false
116
+ ) {
118
117
  const routeInfo = routerService.recognize(url);
119
- activeTransaction = startTransaction({
118
+ Sentry.startBrowserTracingPageLoadSpan(client, {
120
119
  name: `route:${routeInfo.name}`,
121
120
  op: 'pageload',
122
121
  origin: 'auto.pageload.ember',
@@ -126,20 +125,29 @@ export function _instrumentEmberRouter(
126
125
  'routing.instrumentation': '@sentry/ember',
127
126
  },
128
127
  });
128
+ activeRootSpan = getActiveSpan();
129
129
  }
130
130
 
131
131
  const finishActiveTransaction = (_: unknown, nextInstance: unknown): void => {
132
132
  if (nextInstance) {
133
133
  return;
134
134
  }
135
- activeTransaction?.end();
135
+ activeRootSpan?.end();
136
136
  getBackburner().off('end', finishActiveTransaction);
137
137
  };
138
138
 
139
+ if (
140
+ browserTracingOptions.startTransactionOnLocationChange === false &&
141
+ browserTracingOptions.instrumentNavigation === false
142
+ ) {
143
+ return;
144
+ }
145
+
139
146
  routerService.on('routeWillChange', (transition: Transition) => {
140
147
  const { fromRoute, toRoute } = getTransitionInformation(transition, routerService);
141
- activeTransaction?.end();
142
- activeTransaction = startTransaction({
148
+ activeRootSpan?.end();
149
+
150
+ Sentry.startBrowserTracingNavigationSpan(client, {
143
151
  name: `route:${toRoute}`,
144
152
  op: 'navigation',
145
153
  origin: 'auto.navigation.ember',
@@ -149,30 +157,31 @@ export function _instrumentEmberRouter(
149
157
  'routing.instrumentation': '@sentry/ember',
150
158
  },
151
159
  });
160
+
161
+ activeRootSpan = getActiveSpan();
162
+
152
163
  transitionSpan = startInactiveSpan({
164
+ attributes: {
165
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.ember',
166
+ },
153
167
  op: 'ui.ember.transition',
154
168
  name: `route:${fromRoute} -> route:${toRoute}`,
155
- origin: 'auto.ui.ember',
156
169
  });
157
170
  });
158
171
 
159
172
  routerService.on('routeDidChange', () => {
160
- if (!transitionSpan || !activeTransaction) {
173
+ if (!transitionSpan || !activeRootSpan) {
161
174
  return;
162
175
  }
163
176
  transitionSpan.end();
164
177
 
165
178
  if (disableRunloopPerformance) {
166
- activeTransaction.end();
179
+ activeRootSpan.end();
167
180
  return;
168
181
  }
169
182
 
170
183
  getBackburner().on('end', finishActiveTransaction);
171
184
  });
172
-
173
- return {
174
- startTransaction,
175
- };
176
185
  }
177
186
 
178
187
  function _instrumentEmberRunloop(config: EmberSentryConfig): void {
@@ -212,9 +221,11 @@ function _instrumentEmberRunloop(config: EmberSentryConfig): void {
212
221
 
213
222
  if ((now - currentQueueStart) * 1000 >= minQueueDuration) {
214
223
  startInactiveSpan({
224
+ attributes: {
225
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.ember',
226
+ },
215
227
  name: 'runloop',
216
228
  op: `ui.ember.runloop.${queue}`,
217
- origin: 'auto.ui.ember',
218
229
  startTimestamp: currentQueueStart,
219
230
  })?.end(now);
220
231
  }
@@ -370,7 +381,9 @@ function _instrumentInitialLoad(config: EmberSentryConfig): void {
370
381
  startInactiveSpan({
371
382
  op: 'ui.ember.init',
372
383
  name: 'init',
373
- origin: 'auto.ui.ember',
384
+ attributes: {
385
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.ember',
386
+ },
374
387
  startTimestamp,
375
388
  })?.end(endTimestamp);
376
389
  performance.clearMarks(startName);
@@ -404,61 +417,63 @@ export async function instrumentForPerformance(appInstance: ApplicationInstance)
404
417
  // Maintaining backwards compatibility with config.browserTracingOptions, but passing it with Sentry options is preferred.
405
418
  const browserTracingOptions = config.browserTracingOptions || config.sentry.browserTracingOptions || {};
406
419
 
407
- const { BrowserTracing } = await import('@sentry/browser');
420
+ const { browserTracingIntegration } = await import('@sentry/browser');
408
421
 
409
422
  const idleTimeout = config.transitionTimeout || 5000;
410
423
 
411
- const browserTracing = new BrowserTracing({
412
- routingInstrumentation: (customStartTransaction, startTransactionOnPageLoad) => {
413
- // eslint-disable-next-line ember/no-private-routing-service
414
- const routerMain = appInstance.lookup('router:main') as EmberRouterMain;
415
- let routerService = appInstance.lookup('service:router') as RouterService & {
416
- externalRouter?: RouterService;
417
- _hasMountedSentryPerformanceRouting?: boolean;
418
- };
419
-
420
- if (routerService.externalRouter) {
421
- // Using ember-engines-router-service in an engine.
422
- routerService = routerService.externalRouter;
423
- }
424
- if (routerService._hasMountedSentryPerformanceRouting) {
425
- // Routing listens to route changes on the main router, and should not be initialized multiple times per page.
426
- return;
427
- }
428
- if (!routerService.recognize) {
429
- // Router is missing critical functionality to limit cardinality of the transaction names.
430
- return;
431
- }
432
- routerService._hasMountedSentryPerformanceRouting = true;
433
- _instrumentEmberRouter(routerService, routerMain, config, customStartTransaction, startTransactionOnPageLoad);
434
- },
424
+ const browserTracing = browserTracingIntegration({
435
425
  idleTimeout,
436
426
  ...browserTracingOptions,
427
+ instrumentNavigation: false,
428
+ instrumentPageLoad: false,
437
429
  });
438
430
 
439
- if (macroCondition(isTesting())) {
440
- const client = Sentry.getClient();
441
-
442
- if (
443
- client &&
444
- (client as BrowserClient).getIntegrationByName &&
445
- (client as BrowserClient).getIntegrationByName('BrowserTracing')
446
- ) {
447
- // Initializers are called more than once in tests, causing the integrations to not be setup correctly.
448
- return;
449
- }
450
- }
431
+ const client = Sentry.getClient<BrowserClient>();
432
+
433
+ const isAlreadyInitialized = macroCondition(isTesting()) ? !!client?.getIntegrationByName('BrowserTracing') : false;
451
434
 
452
- const client = Sentry.getClient();
453
435
  if (client && client.addIntegration) {
454
436
  client.addIntegration(browserTracing);
455
437
  }
456
438
 
439
+ // We _always_ call this, as it triggers the page load & navigation spans
440
+ _instrumentNavigation(appInstance, config);
441
+
442
+ // Skip instrumenting the stuff below again in tests, as these are not reset between tests
443
+ if (isAlreadyInitialized) {
444
+ return;
445
+ }
446
+
457
447
  _instrumentEmberRunloop(config);
458
448
  _instrumentComponents(config);
459
449
  _instrumentInitialLoad(config);
460
450
  }
461
451
 
452
+ function _instrumentNavigation(appInstance: ApplicationInstance, config: EmberSentryConfig): void {
453
+ // eslint-disable-next-line ember/no-private-routing-service
454
+ const routerMain = appInstance.lookup('router:main') as EmberRouterMain;
455
+ let routerService = appInstance.lookup('service:router') as RouterService & {
456
+ externalRouter?: RouterService;
457
+ _hasMountedSentryPerformanceRouting?: boolean;
458
+ };
459
+
460
+ if (routerService.externalRouter) {
461
+ // Using ember-engines-router-service in an engine.
462
+ routerService = routerService.externalRouter;
463
+ }
464
+ if (routerService._hasMountedSentryPerformanceRouting) {
465
+ // Routing listens to route changes on the main router, and should not be initialized multiple times per page.
466
+ return;
467
+ }
468
+ if (!routerService.recognize) {
469
+ // Router is missing critical functionality to limit cardinality of the transaction names.
470
+ return;
471
+ }
472
+
473
+ routerService._hasMountedSentryPerformanceRouting = true;
474
+ _instrumentEmberRouter(routerService, routerMain, config);
475
+ }
476
+
462
477
  export default {
463
478
  initialize,
464
479
  };
package/addon/types.ts CHANGED
@@ -1,7 +1,9 @@
1
- import type { BrowserOptions, BrowserTracing } from '@sentry/browser';
1
+ import type { BrowserOptions, BrowserTracing, browserTracingIntegration } from '@sentry/browser';
2
2
  import type { Transaction, TransactionContext } from '@sentry/types';
3
3
 
4
- type BrowserTracingOptions = ConstructorParameters<typeof BrowserTracing>[0];
4
+ type BrowserTracingOptions = Parameters<typeof browserTracingIntegration>[0] &
5
+ // eslint-disable-next-line deprecation/deprecation
6
+ ConstructorParameters<typeof BrowserTracing>[0];
5
7
 
6
8
  export type EmberSentryConfig = {
7
9
  sentry: BrowserOptions & { browserTracingOptions?: BrowserTracingOptions };
@@ -31,7 +33,7 @@ export interface EmberRouterMain {
31
33
  rootURL: string;
32
34
  };
33
35
  }
34
-
36
+ /** @deprecated This will be removed in v8. */
35
37
  export type StartTransactionFunction = (context: TransactionContext) => Transaction | undefined;
36
38
 
37
39
  export type GlobalConfig = {
@@ -1,10 +1,8 @@
1
1
  import type ApplicationInstance from '@ember/application/instance';
2
2
  import type RouterService from '@ember/routing/router-service';
3
- import type { EmberRouterMain, EmberSentryConfig, StartTransactionFunction } from '../types';
3
+ import type { EmberRouterMain, EmberSentryConfig } from '../types';
4
4
  export declare function initialize(appInstance: ApplicationInstance): void;
5
- export declare function _instrumentEmberRouter(routerService: RouterService, routerMain: EmberRouterMain, config: EmberSentryConfig, startTransaction: StartTransactionFunction, startTransactionOnPageLoad?: boolean): {
6
- startTransaction: StartTransactionFunction;
7
- };
5
+ export declare function _instrumentEmberRouter(routerService: RouterService, routerMain: EmberRouterMain, config: EmberSentryConfig): void;
8
6
  export declare function instrumentForPerformance(appInstance: ApplicationInstance): Promise<void>;
9
7
  declare const _default: {
10
8
  initialize: typeof initialize;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/ember",
3
- "version": "7.98.0",
3
+ "version": "7.100.0",
4
4
  "description": "Official Sentry SDK for Ember.js",
5
5
  "repository": "git://github.com/getsentry/sentry-javascript.git",
6
6
  "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/ember",
@@ -32,10 +32,10 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "@embroider/macros": "^1.9.0",
35
- "@sentry/browser": "7.98.0",
36
- "@sentry/core": "7.98.0",
37
- "@sentry/types": "7.98.0",
38
- "@sentry/utils": "7.98.0",
35
+ "@sentry/browser": "7.100.0",
36
+ "@sentry/core": "7.100.0",
37
+ "@sentry/types": "7.100.0",
38
+ "@sentry/utils": "7.100.0",
39
39
  "ember-auto-import": "^1.12.1 || ^2.4.3",
40
40
  "ember-cli-babel": "^7.26.11",
41
41
  "ember-cli-htmlbars": "^6.1.1",
package/types.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import type { BrowserOptions, BrowserTracing } from '@sentry/browser';
1
+ import type { BrowserOptions, BrowserTracing, browserTracingIntegration } from '@sentry/browser';
2
2
  import type { Transaction, TransactionContext } from '@sentry/types';
3
- type BrowserTracingOptions = ConstructorParameters<typeof BrowserTracing>[0];
3
+ type BrowserTracingOptions = Parameters<typeof browserTracingIntegration>[0] & ConstructorParameters<typeof BrowserTracing>[0];
4
4
  export type EmberSentryConfig = {
5
5
  sentry: BrowserOptions & {
6
6
  browserTracingOptions?: BrowserTracingOptions;
@@ -28,6 +28,7 @@ export interface EmberRouterMain {
28
28
  rootURL: string;
29
29
  };
30
30
  }
31
+ /** @deprecated This will be removed in v8. */
31
32
  export type StartTransactionFunction = (context: TransactionContext) => Transaction | undefined;
32
33
  export type GlobalConfig = {
33
34
  __sentryEmberConfig: EmberSentryConfig['sentry'];