@sentry/ember 10.70.0 → 11.0.0-alpha.1

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/.oxlintrc.json CHANGED
@@ -8,12 +8,6 @@
8
8
  "browser": true,
9
9
  "node": false
10
10
  }
11
- },
12
- {
13
- "files": ["{addon,app,tests}/**/*.{js,ts,d.ts}"],
14
- "rules": {
15
- "import/no-unresolved": "off"
16
- }
17
11
  }
18
12
  ]
19
13
  }
package/addon/index.ts CHANGED
@@ -4,6 +4,8 @@
4
4
  import { assert } from '@ember/debug';
5
5
  import type Route from '@ember/routing/route';
6
6
  import { getOwnConfig } from '@embroider/macros';
7
+ import { CODE_FUNCTION_NAME, SENTRY_OP } from '@sentry/conventions/attributes';
8
+ import { GENERAL_FUNCTION_SPAN_OP } from '@sentry/conventions/op';
7
9
  import type { BrowserOptions } from '@sentry/browser';
8
10
  import { startSpan } from '@sentry/browser';
9
11
  import * as Sentry from '@sentry/browser';
@@ -54,7 +56,7 @@ type RouteConstructor = new (...args: ConstructorParameters<typeof Route>) => Ro
54
56
  export const instrumentRoutePerformance = <T extends RouteConstructor>(BaseRoute: T): T => {
55
57
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
56
58
  const instrumentFunction = async <X extends (...args: unknown[]) => any>(
57
- op: string,
59
+ hookName: string,
58
60
  name: string,
59
61
  fn: X,
60
62
  args: Parameters<X>,
@@ -65,8 +67,9 @@ export const instrumentRoutePerformance = <T extends RouteConstructor>(BaseRoute
65
67
  attributes: {
66
68
  [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,
67
69
  [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.ember',
70
+ [SENTRY_OP]: GENERAL_FUNCTION_SPAN_OP,
71
+ [CODE_FUNCTION_NAME]: hookName,
68
72
  },
69
- op,
70
73
  name,
71
74
  onlyIfParent: true,
72
75
  },
@@ -82,32 +85,20 @@ export const instrumentRoutePerformance = <T extends RouteConstructor>(BaseRoute
82
85
  // @ts-expect-error TS2545 We do not need to redefine a constructor here
83
86
  [routeName]: class extends BaseRoute {
84
87
  public beforeModel(...args: unknown[]): void | Promise<unknown> {
85
- return instrumentFunction(
86
- 'ui.ember.route.before_model',
87
- this.fullRouteName,
88
- super.beforeModel.bind(this),
89
- args,
90
- 'custom',
91
- );
88
+ return instrumentFunction('beforeModel', this.fullRouteName, super.beforeModel.bind(this), args, 'custom');
92
89
  }
93
90
 
94
91
  public async model(...args: unknown[]): Promise<unknown> {
95
- return instrumentFunction('ui.ember.route.model', this.fullRouteName, super.model.bind(this), args, 'custom');
92
+ return instrumentFunction('model', this.fullRouteName, super.model.bind(this), args, 'custom');
96
93
  }
97
94
 
98
95
  public afterModel(...args: unknown[]): void | Promise<unknown> {
99
- return instrumentFunction(
100
- 'ui.ember.route.after_model',
101
- this.fullRouteName,
102
- super.afterModel.bind(this),
103
- args,
104
- 'custom',
105
- );
96
+ return instrumentFunction('afterModel', this.fullRouteName, super.afterModel.bind(this), args, 'custom');
106
97
  }
107
98
 
108
99
  public setupController(...args: unknown[]): void | Promise<unknown> {
109
100
  return instrumentFunction(
110
- 'ui.ember.route.setup_controller',
101
+ 'setupController',
111
102
  this.fullRouteName,
112
103
  super.setupController.bind(this),
113
104
  args,
@@ -14,7 +14,7 @@ import {
14
14
  import type { Client, Span } from '@sentry/core';
15
15
  import type { EmberRouterMain } from '../types';
16
16
  import { getBackburner } from './performance';
17
- import { URL_FULL, URL_PATH, URL_TEMPLATE } from '@sentry/conventions/attributes';
17
+ import { SENTRY_OP, URL_FULL, URL_PATH, URL_TEMPLATE } from '@sentry/conventions/attributes';
18
18
 
19
19
  type TransitionWithIntent = Transition & { intent?: { url?: string } };
20
20
 
@@ -200,9 +200,10 @@ function _instrumentEmberRouter(
200
200
 
201
201
  transitionSpan = startInactiveSpan({
202
202
  attributes: {
203
+ // TODO(conventions): Replace `'router'` with the `router` span op constant once it is released in `@sentry/conventions`.
204
+ [SENTRY_OP]: 'router',
203
205
  [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.ember',
204
206
  },
205
- op: 'ui.ember.transition',
206
207
  name: `route:${fromRoute} -> route:${toRoute}`,
207
208
  onlyIfParent: true,
208
209
  });
@@ -1,6 +1,8 @@
1
1
  import { subscribe } from '@ember/instrumentation';
2
2
  import { scheduleOnce } from '@ember/runloop';
3
3
  import type { EmberRunQueues } from '@ember/runloop/-private/types';
4
+ import { SENTRY_OP, UI_COMPONENT_NAME } from '@sentry/conventions/attributes';
5
+ import { BROWSER_UI_RENDER_SPAN_OP, BROWSER_UI_TASK_SPAN_OP, GENERAL_FUNCTION_SPAN_OP } from '@sentry/conventions/op';
4
6
  import { getActiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startInactiveSpan } from '@sentry/browser';
5
7
  import type { Span } from '@sentry/core';
6
8
  import { browserPerformanceTimeOrigin, timestampInSeconds } from '@sentry/core';
@@ -13,13 +15,10 @@ type Payload = {
13
15
  };
14
16
 
15
17
  type RenderEntry = {
16
- payload: Payload;
17
18
  now: number;
18
19
  };
19
20
 
20
- interface RenderEntries {
21
- [name: string]: RenderEntry;
22
- }
21
+ export type RenderEntries = WeakMap<Payload, RenderEntry>;
23
22
 
24
23
  /** This is global, so should only be run once in tests! */
25
24
  export function instrumentGlobalsForPerformance(config: {
@@ -89,10 +88,11 @@ function _instrumentEmberRunloop(config: { minimumRunloopQueueDuration?: number
89
88
  if ((now - currentQueueStart) * 1000 >= minQueueDuration) {
90
89
  startInactiveSpan({
91
90
  attributes: {
91
+ [SENTRY_OP]: BROWSER_UI_TASK_SPAN_OP,
92
92
  [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.ember',
93
+ 'ember.runloop.queue': queue,
93
94
  },
94
95
  name: 'runloop',
95
- op: `ui.ember.runloop.${queue}`,
96
96
  startTime: currentQueueStart,
97
97
  onlyIfParent: true,
98
98
  })?.end(now);
@@ -124,36 +124,39 @@ function _instrumentEmberRunloop(config: { minimumRunloopQueueDuration?: number
124
124
  });
125
125
  }
126
126
 
127
- function processComponentRenderBefore(payload: Payload, beforeEntries: RenderEntries): void {
128
- const info = {
129
- payload,
130
- now: timestampInSeconds(),
131
- };
132
- beforeEntries[payload.object] = info;
127
+ export function _processComponentRenderBefore(payload: Payload, beforeEntries: RenderEntries): void {
128
+ beforeEntries.set(payload, { now: timestampInSeconds() });
133
129
  }
134
130
 
135
- function processComponentRenderAfter(
131
+ export function _processComponentRenderAfter(
136
132
  payload: Payload,
137
133
  beforeEntries: RenderEntries,
138
134
  op: string,
139
135
  minComponentDuration: number,
140
136
  ): void {
141
- const begin = beforeEntries[payload.object];
137
+ const begin = beforeEntries.get(payload);
142
138
 
143
139
  if (!begin) {
144
140
  return;
145
141
  }
146
142
 
143
+ // A WeakMap entry cannot outlive its payload, but delete promptly anyway
144
+ // so a long-lived payload doesn't keep the entry around between renders.
145
+ beforeEntries.delete(payload);
146
+
147
147
  const now = timestampInSeconds();
148
148
  const componentRenderDuration = now - begin.now;
149
149
 
150
+ const name = payload.containerKey || payload.object;
151
+
150
152
  if (componentRenderDuration * 1000 >= minComponentDuration) {
151
153
  startInactiveSpan({
152
- name: payload.containerKey || payload.object,
153
- op,
154
+ name,
154
155
  startTime: begin.now,
155
156
  attributes: {
157
+ [SENTRY_OP]: op,
156
158
  [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.ember',
159
+ [UI_COMPONENT_NAME]: name,
157
160
  },
158
161
  onlyIfParent: true,
159
162
  })?.end(now);
@@ -168,27 +171,27 @@ function _instrumentComponents(config: {
168
171
 
169
172
  const minComponentDuration = minimumComponentRenderDuration ?? 2;
170
173
 
171
- const beforeEntries = {} as RenderEntries;
172
- const beforeComponentDefinitionEntries = {} as RenderEntries;
174
+ const beforeEntries: RenderEntries = new WeakMap();
175
+ const beforeComponentDefinitionEntries: RenderEntries = new WeakMap();
173
176
 
174
177
  function _subscribeToRenderEvents(): void {
175
178
  subscribe('render.component', {
176
179
  before(_name: string, _timestamp: number, payload: Payload) {
177
- processComponentRenderBefore(payload, beforeEntries);
180
+ _processComponentRenderBefore(payload, beforeEntries);
178
181
  },
179
182
 
180
183
  after(_name: string, _timestamp: number, payload: Payload, _beganIndex: number) {
181
- processComponentRenderAfter(payload, beforeEntries, 'ui.ember.component.render', minComponentDuration);
184
+ _processComponentRenderAfter(payload, beforeEntries, BROWSER_UI_RENDER_SPAN_OP, minComponentDuration);
182
185
  },
183
186
  });
184
187
  if (enableComponentDefinitions) {
185
188
  subscribe('render.getComponentDefinition', {
186
189
  before(_name: string, _timestamp: number, payload: Payload) {
187
- processComponentRenderBefore(payload, beforeComponentDefinitionEntries);
190
+ _processComponentRenderBefore(payload, beforeComponentDefinitionEntries);
188
191
  },
189
192
 
190
193
  after(_name: string, _timestamp: number, payload: Payload, _beganIndex: number) {
191
- processComponentRenderAfter(payload, beforeComponentDefinitionEntries, 'ui.ember.component.definition', 0);
194
+ _processComponentRenderAfter(payload, beforeComponentDefinitionEntries, GENERAL_FUNCTION_SPAN_OP, 0);
192
195
  },
193
196
  });
194
197
  }
@@ -230,9 +233,10 @@ function _instrumentInitialLoad(): void {
230
233
  const endTime = startTime + measure.duration / 1000;
231
234
 
232
235
  startInactiveSpan({
233
- op: 'ui.ember.init',
234
236
  name: 'init',
235
237
  attributes: {
238
+ // TODO(v11): Replace with the `ui.mount` constant from `@sentry/conventions/op` once it is registered there.
239
+ [SENTRY_OP]: 'ui.mount',
236
240
  [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.ember',
237
241
  },
238
242
  startTime,
@@ -22,7 +22,7 @@ export function getSentryConfig(): EmberSentryConfig {
22
22
 
23
23
  export function getBackburner(): Pick<ExtendedBackburner, 'on' | 'off'> {
24
24
  if (_backburner) {
25
- return _backburner as unknown as Pick<ExtendedBackburner, 'on' | 'off'>;
25
+ return _backburner;
26
26
  }
27
27
 
28
28
  if ((run as unknown as { backburner?: Pick<ExtendedBackburner, 'on' | 'off'> }).backburner) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/ember",
3
- "version": "10.70.0",
3
+ "version": "11.0.0-alpha.1",
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",
@@ -21,9 +21,9 @@
21
21
  "clean": "yarn rimraf sentry-ember-*.tgz dist tmp build .node_modules.ember-try package.json.ember-try instance-initializers index.d.ts runloop.d.ts types.d.ts",
22
22
  "lint": "run-p lint:js lint:hbs lint:ts",
23
23
  "lint:hbs": "ember-template-lint .",
24
- "lint:js": "OXLINT_TSGOLINT_DANGEROUSLY_SUPPRESS_PROGRAM_DIAGNOSTICS=true oxlint . --type-aware",
24
+ "lint:js": "oxlint . --type-aware",
25
25
  "lint:ts": "tsc",
26
- "lint:fix": "OXLINT_TSGOLINT_DANGEROUSLY_SUPPRESS_PROGRAM_DIAGNOSTICS=true oxlint . --fix --type-aware",
26
+ "lint:fix": "oxlint . --fix --type-aware",
27
27
  "start": "ember serve",
28
28
  "test": "ember b --prod && ember test",
29
29
  "prepack": "ember ts:precompile",
@@ -32,9 +32,9 @@
32
32
  "dependencies": {
33
33
  "@babel/core": "^7.29.6",
34
34
  "@embroider/macros": "^1.16.0",
35
- "@sentry/browser": "10.70.0",
36
- "@sentry/core": "10.70.0",
37
- "@sentry/conventions": "^0.16.0",
35
+ "@sentry/browser": "11.0.0-alpha.1",
36
+ "@sentry/core": "11.0.0-alpha.1",
37
+ "@sentry/conventions": "^0.19.0",
38
38
  "ember-auto-import": "^2.7.2",
39
39
  "ember-cli-babel": "^8.2.0",
40
40
  "ember-cli-htmlbars": "^6.1.1",
@@ -78,10 +78,11 @@
78
78
  "qunit": "~2.22.0",
79
79
  "qunit-dom": "~3.5.0",
80
80
  "sinon": "21.0.1",
81
+ "typescript": "~5.8.0",
81
82
  "webpack": "~5.104.1"
82
83
  },
83
84
  "engines": {
84
- "node": ">=18"
85
+ "node": ">=20.19.0 <22.0.0 || >=22.12.0 <23.0.0 || >=23.2.0"
85
86
  },
86
87
  "ember": {
87
88
  "edition": "octane"
package/tsconfig.json CHANGED
@@ -10,16 +10,15 @@
10
10
  "strictPropertyInitialization": true,
11
11
  "noEmitOnError": false,
12
12
  "noEmit": true,
13
- "baseUrl": ".",
14
13
  "experimentalDecorators": true,
15
14
  "paths": {
16
- "dummy/tests/*": ["tests/*"],
17
- "dummy/*": ["tests/dummy/app/*", "app/*"],
18
- "@sentry/ember": ["addon"],
19
- "@sentry/ember/*": ["addon/*"],
20
- "@sentry/ember/test-support": ["addon-test-support"],
21
- "@sentry/ember/test-support/*": ["addon-test-support/*"],
22
- "*": ["types/*"]
15
+ "dummy/tests/*": ["./tests/*"],
16
+ "dummy/*": ["./tests/dummy/app/*", "./app/*"],
17
+ "@sentry/ember": ["./addon"],
18
+ "@sentry/ember/*": ["./addon/*"],
19
+ "@sentry/ember/test-support": ["./addon-test-support"],
20
+ "@sentry/ember/test-support/*": ["./addon-test-support/*"],
21
+ "*": ["./types/*"]
23
22
  }
24
23
  },
25
24
  "include": ["app/**/*", "addon/**/*", "tests/**/*", "types/**/*", "test-support/**/*", "addon-test-support/**/*"]
@@ -1,3 +1,12 @@
1
+ type Payload = {
2
+ containerKey: string;
3
+ initialRender: true;
4
+ object: string;
5
+ };
6
+ type RenderEntry = {
7
+ now: number;
8
+ };
9
+ export type RenderEntries = WeakMap<Payload, RenderEntry>;
1
10
  /** This is global, so should only be run once in tests! */
2
11
  export declare function instrumentGlobalsForPerformance(config: {
3
12
  disableRunloopPerformance?: boolean;
@@ -7,3 +16,6 @@ export declare function instrumentGlobalsForPerformance(config: {
7
16
  enableComponentDefinitions?: boolean;
8
17
  disableInitialLoadInstrumentation?: boolean;
9
18
  }): void;
19
+ export declare function _processComponentRenderBefore(payload: Payload, beforeEntries: RenderEntries): void;
20
+ export declare function _processComponentRenderAfter(payload: Payload, beforeEntries: RenderEntries, op: string, minComponentDuration: number): void;
21
+ export {};