@sentry/ember 7.1.1 → 7.2.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/package.json +5 -5
- package/addon/ember.d.ts +0 -6
- package/addon/index.ts +0 -122
- package/addon/instance-initializers/sentry-performance.ts +0 -412
- package/addon/runloop.d.ts +0 -19
- package/addon/types.ts +0 -24
- package/app/instance-initializers/sentry-performance.js +0 -1
- package/config/environment.js +0 -5
- package/ember.d.ts +0 -6
- package/index.d.ts +0 -15
- package/index.js +0 -52
- package/instance-initializers/sentry-performance.d.ts +0 -11
- package/runloop.d.ts +0 -19
- package/scripts/run-CI-tests.js +0 -17
- package/tsconfig.json +0 -28
- package/types.d.ts +0 -23
- package/vendor/initial-load-body.js +0 -3
- package/vendor/initial-load-head.js +0 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/ember",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.2.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",
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@embroider/macros": "~0.47.2",
|
|
33
|
-
"@sentry/browser": "7.
|
|
34
|
-
"@sentry/tracing": "7.
|
|
35
|
-
"@sentry/types": "7.
|
|
36
|
-
"@sentry/utils": "7.
|
|
33
|
+
"@sentry/browser": "7.2.0",
|
|
34
|
+
"@sentry/tracing": "7.2.0",
|
|
35
|
+
"@sentry/types": "7.2.0",
|
|
36
|
+
"@sentry/utils": "7.2.0",
|
|
37
37
|
"ember-auto-import": "~1.12.1 || ~2.2.0",
|
|
38
38
|
"ember-cli-babel": "~7.26.6",
|
|
39
39
|
"ember-cli-htmlbars": "^6.0.1",
|
package/addon/ember.d.ts
DELETED
package/addon/index.ts
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import * as Sentry from '@sentry/browser';
|
|
2
|
-
import { SDK_VERSION, BrowserOptions } from '@sentry/browser';
|
|
3
|
-
import { macroCondition, isDevelopingApp, getOwnConfig } from '@embroider/macros';
|
|
4
|
-
import { next } from '@ember/runloop';
|
|
5
|
-
import { assert, warn } from '@ember/debug';
|
|
6
|
-
import Ember from 'ember';
|
|
7
|
-
import { timestampWithMs } from '@sentry/utils';
|
|
8
|
-
import { GlobalConfig, OwnConfig } from './types';
|
|
9
|
-
import { getGlobalObject } from '@sentry/utils';
|
|
10
|
-
|
|
11
|
-
function _getSentryInitConfig() {
|
|
12
|
-
const _global = getGlobalObject<GlobalConfig>();
|
|
13
|
-
_global.__sentryEmberConfig = _global.__sentryEmberConfig ?? {};
|
|
14
|
-
return _global.__sentryEmberConfig;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function InitSentryForEmber(_runtimeConfig?: BrowserOptions) {
|
|
18
|
-
const environmentConfig = getOwnConfig<OwnConfig>().sentryConfig;
|
|
19
|
-
|
|
20
|
-
assert('Missing configuration.', environmentConfig);
|
|
21
|
-
assert('Missing configuration for Sentry.', environmentConfig.sentry || _runtimeConfig);
|
|
22
|
-
|
|
23
|
-
if (!environmentConfig.sentry) {
|
|
24
|
-
// If environment config is not specified but the above assertion passes, use runtime config.
|
|
25
|
-
environmentConfig.sentry = { ..._runtimeConfig } as any;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Merge runtime config into environment config, preferring runtime.
|
|
29
|
-
Object.assign(environmentConfig.sentry, _runtimeConfig || {});
|
|
30
|
-
const initConfig = Object.assign({}, environmentConfig.sentry);
|
|
31
|
-
|
|
32
|
-
initConfig._metadata = initConfig._metadata || {};
|
|
33
|
-
initConfig._metadata.sdk = {
|
|
34
|
-
name: 'sentry.javascript.ember',
|
|
35
|
-
packages: [
|
|
36
|
-
{
|
|
37
|
-
name: 'npm:@sentry/ember',
|
|
38
|
-
version: SDK_VERSION,
|
|
39
|
-
},
|
|
40
|
-
],
|
|
41
|
-
version: SDK_VERSION,
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
// Persist Sentry init options so they are identical when performance initializers call init again.
|
|
45
|
-
const sentryInitConfig = _getSentryInitConfig();
|
|
46
|
-
Object.assign(sentryInitConfig, initConfig);
|
|
47
|
-
|
|
48
|
-
Sentry.init(initConfig);
|
|
49
|
-
|
|
50
|
-
if (macroCondition(isDevelopingApp())) {
|
|
51
|
-
if (environmentConfig.ignoreEmberOnErrorWarning) {
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
next(null, function () {
|
|
55
|
-
warn(
|
|
56
|
-
'Ember.onerror found. Using Ember.onerror can hide some errors (such as flushed runloop errors) from Sentry. Use Sentry.captureException to capture errors within Ember.onError or remove it to have errors caught by Sentry directly. This error can be silenced via addon configuration.',
|
|
57
|
-
!Ember.onerror,
|
|
58
|
-
{
|
|
59
|
-
id: '@sentry/ember.ember-onerror-detected',
|
|
60
|
-
},
|
|
61
|
-
);
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export const getActiveTransaction = () => {
|
|
67
|
-
return Sentry.getCurrentHub()?.getScope()?.getTransaction();
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
export const instrumentRoutePerformance = (BaseRoute: any) => {
|
|
71
|
-
const instrumentFunction = async (op: string, description: string, fn: Function, args: any) => {
|
|
72
|
-
const startTimestamp = timestampWithMs();
|
|
73
|
-
const result = await fn(...args);
|
|
74
|
-
|
|
75
|
-
const currentTransaction = getActiveTransaction();
|
|
76
|
-
if (!currentTransaction) {
|
|
77
|
-
return result;
|
|
78
|
-
}
|
|
79
|
-
currentTransaction.startChild({ op, description, startTimestamp }).finish();
|
|
80
|
-
return result;
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
return {
|
|
84
|
-
[BaseRoute.name]: class extends BaseRoute {
|
|
85
|
-
beforeModel(...args: any[]) {
|
|
86
|
-
return instrumentFunction(
|
|
87
|
-
'ember.route.beforeModel',
|
|
88
|
-
(<any>this).fullRouteName,
|
|
89
|
-
super.beforeModel.bind(this),
|
|
90
|
-
args,
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
async model(...args: any[]) {
|
|
95
|
-
return instrumentFunction('ember.route.model', (<any>this).fullRouteName, super.model.bind(this), args);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
async afterModel(...args: any[]) {
|
|
99
|
-
return instrumentFunction(
|
|
100
|
-
'ember.route.afterModel',
|
|
101
|
-
(<any>this).fullRouteName,
|
|
102
|
-
super.afterModel.bind(this),
|
|
103
|
-
args,
|
|
104
|
-
);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
async setupController(...args: any[]) {
|
|
108
|
-
return instrumentFunction(
|
|
109
|
-
'ember.route.setupController',
|
|
110
|
-
(<any>this).fullRouteName,
|
|
111
|
-
super.setupController.bind(this),
|
|
112
|
-
args,
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
},
|
|
116
|
-
}[BaseRoute.name];
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
export * from '@sentry/browser';
|
|
120
|
-
|
|
121
|
-
// init is now the preferred way to call initialization for this addon.
|
|
122
|
-
export const init = InitSentryForEmber;
|
|
@@ -1,412 +0,0 @@
|
|
|
1
|
-
import ApplicationInstance from '@ember/application/instance';
|
|
2
|
-
import Ember from 'ember';
|
|
3
|
-
import { run, _backburner, scheduleOnce } from '@ember/runloop';
|
|
4
|
-
import * as Sentry from '@sentry/browser';
|
|
5
|
-
import { ExtendedBackburner } from '@sentry/ember/runloop';
|
|
6
|
-
import { Span, Transaction, Integration } from '@sentry/types';
|
|
7
|
-
import { EmberRunQueues } from '@ember/runloop/-private/types';
|
|
8
|
-
import { getActiveTransaction } from '..';
|
|
9
|
-
import { browserPerformanceTimeOrigin, getGlobalObject, timestampWithMs } from '@sentry/utils';
|
|
10
|
-
import { macroCondition, isTesting, getOwnConfig } from '@embroider/macros';
|
|
11
|
-
import { EmberSentryConfig, GlobalConfig, OwnConfig } from '../types';
|
|
12
|
-
|
|
13
|
-
function getSentryConfig() {
|
|
14
|
-
const _global = getGlobalObject<GlobalConfig>();
|
|
15
|
-
_global.__sentryEmberConfig = _global.__sentryEmberConfig ?? {};
|
|
16
|
-
const environmentConfig = getOwnConfig<OwnConfig>().sentryConfig;
|
|
17
|
-
if (!environmentConfig.sentry) {
|
|
18
|
-
environmentConfig.sentry = {
|
|
19
|
-
browserTracingOptions: {},
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
Object.assign(environmentConfig.sentry, _global.__sentryEmberConfig);
|
|
23
|
-
return environmentConfig;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function initialize(appInstance: ApplicationInstance): void {
|
|
27
|
-
const config = getSentryConfig();
|
|
28
|
-
if (config['disablePerformance']) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
const performancePromise = instrumentForPerformance(appInstance);
|
|
32
|
-
if (macroCondition(isTesting())) {
|
|
33
|
-
(<any>window)._sentryPerformanceLoad = performancePromise;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function getBackburner(): Pick<ExtendedBackburner, 'on' | 'off'> {
|
|
38
|
-
if (_backburner) {
|
|
39
|
-
return _backburner;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (run.backburner) {
|
|
43
|
-
return run.backburner;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return {
|
|
47
|
-
on() {},
|
|
48
|
-
off() {},
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function getTransitionInformation(transition: any, router: any) {
|
|
53
|
-
const fromRoute = transition?.from?.name;
|
|
54
|
-
const toRoute = transition && transition.to ? transition.to.name : router.currentRouteName;
|
|
55
|
-
return {
|
|
56
|
-
fromRoute,
|
|
57
|
-
toRoute,
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function getLocationURL(location: any) {
|
|
62
|
-
if (!location || !location.getURL || !location.formatURL) {
|
|
63
|
-
return '';
|
|
64
|
-
}
|
|
65
|
-
const url = location.formatURL(location.getURL());
|
|
66
|
-
|
|
67
|
-
if (location.implementation === 'hash') {
|
|
68
|
-
return `${location.rootURL}${url}`;
|
|
69
|
-
}
|
|
70
|
-
return url;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export function _instrumentEmberRouter(
|
|
74
|
-
routerService: any,
|
|
75
|
-
routerMain: any,
|
|
76
|
-
config: EmberSentryConfig,
|
|
77
|
-
startTransaction: Function,
|
|
78
|
-
startTransactionOnPageLoad?: boolean,
|
|
79
|
-
) {
|
|
80
|
-
const { disableRunloopPerformance } = config;
|
|
81
|
-
const location = routerMain.location;
|
|
82
|
-
let activeTransaction: Transaction;
|
|
83
|
-
let transitionSpan: Span;
|
|
84
|
-
|
|
85
|
-
const url = getLocationURL(location);
|
|
86
|
-
|
|
87
|
-
if (macroCondition(isTesting())) {
|
|
88
|
-
routerService._sentryInstrumented = true;
|
|
89
|
-
routerService._startTransaction = startTransaction;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (startTransactionOnPageLoad && url) {
|
|
93
|
-
const routeInfo = routerService.recognize(url);
|
|
94
|
-
activeTransaction = startTransaction({
|
|
95
|
-
name: `route:${routeInfo.name}`,
|
|
96
|
-
op: 'pageload',
|
|
97
|
-
tags: {
|
|
98
|
-
url,
|
|
99
|
-
toRoute: routeInfo.name,
|
|
100
|
-
'routing.instrumentation': '@sentry/ember',
|
|
101
|
-
},
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const finishActiveTransaction = function (_: any, nextInstance: any) {
|
|
106
|
-
if (nextInstance) {
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
activeTransaction.finish();
|
|
110
|
-
getBackburner().off('end', finishActiveTransaction);
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
routerService.on('routeWillChange', (transition: any) => {
|
|
114
|
-
const { fromRoute, toRoute } = getTransitionInformation(transition, routerService);
|
|
115
|
-
activeTransaction?.finish();
|
|
116
|
-
activeTransaction = startTransaction({
|
|
117
|
-
name: `route:${toRoute}`,
|
|
118
|
-
op: 'navigation',
|
|
119
|
-
tags: {
|
|
120
|
-
fromRoute,
|
|
121
|
-
toRoute,
|
|
122
|
-
'routing.instrumentation': '@sentry/ember',
|
|
123
|
-
},
|
|
124
|
-
});
|
|
125
|
-
transitionSpan = activeTransaction.startChild({
|
|
126
|
-
op: 'ui.ember.transition',
|
|
127
|
-
description: `route:${fromRoute} -> route:${toRoute}`,
|
|
128
|
-
});
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
routerService.on('routeDidChange', () => {
|
|
132
|
-
if (!transitionSpan || !activeTransaction) {
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
transitionSpan.finish();
|
|
136
|
-
|
|
137
|
-
if (disableRunloopPerformance) {
|
|
138
|
-
activeTransaction.finish();
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
getBackburner().on('end', finishActiveTransaction);
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
return {
|
|
146
|
-
startTransaction,
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function _instrumentEmberRunloop(config: EmberSentryConfig) {
|
|
151
|
-
const { disableRunloopPerformance, minimumRunloopQueueDuration } = config;
|
|
152
|
-
if (disableRunloopPerformance) {
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
let currentQueueStart: number | undefined;
|
|
157
|
-
let currentQueueSpan: Span | undefined;
|
|
158
|
-
const instrumentedEmberQueues = [
|
|
159
|
-
'actions',
|
|
160
|
-
'routerTransitions',
|
|
161
|
-
'render',
|
|
162
|
-
'afterRender',
|
|
163
|
-
'destroy',
|
|
164
|
-
] as EmberRunQueues[];
|
|
165
|
-
|
|
166
|
-
getBackburner().on('begin', (_: any, previousInstance: any) => {
|
|
167
|
-
if (previousInstance) {
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
const activeTransaction = getActiveTransaction();
|
|
171
|
-
if (!activeTransaction) {
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
if (currentQueueSpan) {
|
|
175
|
-
currentQueueSpan.finish();
|
|
176
|
-
}
|
|
177
|
-
currentQueueStart = timestampWithMs();
|
|
178
|
-
|
|
179
|
-
instrumentedEmberQueues.forEach(queue => {
|
|
180
|
-
scheduleOnce(queue, null, () => {
|
|
181
|
-
scheduleOnce(queue, null, () => {
|
|
182
|
-
// Process this queue using the end of the previous queue.
|
|
183
|
-
if (currentQueueStart) {
|
|
184
|
-
const now = timestampWithMs();
|
|
185
|
-
const minQueueDuration = minimumRunloopQueueDuration ?? 5;
|
|
186
|
-
|
|
187
|
-
if ((now - currentQueueStart) * 1000 >= minQueueDuration) {
|
|
188
|
-
activeTransaction
|
|
189
|
-
?.startChild({
|
|
190
|
-
op: `ui.ember.runloop.${queue}`,
|
|
191
|
-
startTimestamp: currentQueueStart,
|
|
192
|
-
endTimestamp: now,
|
|
193
|
-
})
|
|
194
|
-
.finish();
|
|
195
|
-
}
|
|
196
|
-
currentQueueStart = undefined;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// Setup for next queue
|
|
200
|
-
|
|
201
|
-
const stillActiveTransaction = getActiveTransaction();
|
|
202
|
-
if (!stillActiveTransaction) {
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
currentQueueStart = timestampWithMs();
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
getBackburner().on('end', (_: any, nextInstance: any) => {
|
|
211
|
-
if (nextInstance) {
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
if (currentQueueSpan) {
|
|
215
|
-
currentQueueSpan.finish();
|
|
216
|
-
currentQueueSpan = undefined;
|
|
217
|
-
}
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
type Payload = {
|
|
222
|
-
containerKey: string;
|
|
223
|
-
initialRender: true;
|
|
224
|
-
object: string;
|
|
225
|
-
};
|
|
226
|
-
|
|
227
|
-
type RenderEntry = {
|
|
228
|
-
payload: Payload;
|
|
229
|
-
now: number;
|
|
230
|
-
};
|
|
231
|
-
|
|
232
|
-
interface RenderEntries {
|
|
233
|
-
[name: string]: RenderEntry;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
function processComponentRenderBefore(payload: Payload, beforeEntries: RenderEntries) {
|
|
237
|
-
const info = {
|
|
238
|
-
payload,
|
|
239
|
-
now: timestampWithMs(),
|
|
240
|
-
};
|
|
241
|
-
beforeEntries[payload.object] = info;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
function processComponentRenderAfter(
|
|
245
|
-
payload: Payload,
|
|
246
|
-
beforeEntries: RenderEntries,
|
|
247
|
-
op: string,
|
|
248
|
-
minComponentDuration: number,
|
|
249
|
-
) {
|
|
250
|
-
const begin = beforeEntries[payload.object];
|
|
251
|
-
|
|
252
|
-
if (!begin) {
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
const now = timestampWithMs();
|
|
257
|
-
const componentRenderDuration = now - begin.now;
|
|
258
|
-
|
|
259
|
-
if (componentRenderDuration * 1000 >= minComponentDuration) {
|
|
260
|
-
const activeTransaction = getActiveTransaction();
|
|
261
|
-
|
|
262
|
-
activeTransaction?.startChild({
|
|
263
|
-
op,
|
|
264
|
-
description: payload.containerKey || payload.object,
|
|
265
|
-
startTimestamp: begin.now,
|
|
266
|
-
endTimestamp: now,
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
function _instrumentComponents(config: EmberSentryConfig) {
|
|
272
|
-
const { disableInstrumentComponents, minimumComponentRenderDuration, enableComponentDefinitions } = config;
|
|
273
|
-
if (disableInstrumentComponents) {
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
const minComponentDuration = minimumComponentRenderDuration ?? 2;
|
|
278
|
-
|
|
279
|
-
const beforeEntries = {} as RenderEntries;
|
|
280
|
-
const beforeComponentDefinitionEntries = {} as RenderEntries;
|
|
281
|
-
|
|
282
|
-
const subscribe = Ember.subscribe;
|
|
283
|
-
function _subscribeToRenderEvents() {
|
|
284
|
-
subscribe('render.component', {
|
|
285
|
-
before(_name: string, _timestamp: number, payload: Payload) {
|
|
286
|
-
processComponentRenderBefore(payload, beforeEntries);
|
|
287
|
-
},
|
|
288
|
-
|
|
289
|
-
after(_name: string, _timestamp: number, payload: any, _beganIndex: number) {
|
|
290
|
-
processComponentRenderAfter(payload, beforeEntries, 'ui.ember.component.render', minComponentDuration);
|
|
291
|
-
},
|
|
292
|
-
});
|
|
293
|
-
if (enableComponentDefinitions) {
|
|
294
|
-
subscribe('render.getComponentDefinition', {
|
|
295
|
-
before(_name: string, _timestamp: number, payload: Payload) {
|
|
296
|
-
processComponentRenderBefore(payload, beforeComponentDefinitionEntries);
|
|
297
|
-
},
|
|
298
|
-
|
|
299
|
-
after(_name: string, _timestamp: number, payload: any, _beganIndex: number) {
|
|
300
|
-
processComponentRenderAfter(payload, beforeComponentDefinitionEntries, 'ui.ember.component.definition', 0);
|
|
301
|
-
},
|
|
302
|
-
});
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
_subscribeToRenderEvents();
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
function _instrumentInitialLoad(config: EmberSentryConfig) {
|
|
309
|
-
const startName = '@sentry/ember:initial-load-start';
|
|
310
|
-
const endName = '@sentry/ember:initial-load-end';
|
|
311
|
-
|
|
312
|
-
const { performance } = window;
|
|
313
|
-
const HAS_PERFORMANCE = performance && performance.clearMarks && performance.clearMeasures;
|
|
314
|
-
|
|
315
|
-
if (!HAS_PERFORMANCE) {
|
|
316
|
-
return;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
if (config.disableInitialLoadInstrumentation) {
|
|
320
|
-
performance.clearMarks(startName);
|
|
321
|
-
performance.clearMarks(endName);
|
|
322
|
-
return;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// Split performance check in two so clearMarks still happens even if timeOrigin isn't available.
|
|
326
|
-
const HAS_PERFORMANCE_TIMING =
|
|
327
|
-
performance.measure && performance.getEntriesByName && browserPerformanceTimeOrigin !== undefined;
|
|
328
|
-
if (!HAS_PERFORMANCE_TIMING) {
|
|
329
|
-
return;
|
|
330
|
-
}
|
|
331
|
-
const measureName = '@sentry/ember:initial-load';
|
|
332
|
-
|
|
333
|
-
const startMarkExists = performance.getEntriesByName(startName).length > 0;
|
|
334
|
-
const endMarkExists = performance.getEntriesByName(endName).length > 0;
|
|
335
|
-
if (!startMarkExists || !endMarkExists) {
|
|
336
|
-
return;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
performance.measure(measureName, startName, endName);
|
|
340
|
-
const measures = performance.getEntriesByName(measureName);
|
|
341
|
-
const measure = measures[0];
|
|
342
|
-
|
|
343
|
-
const startTimestamp = (measure.startTime + browserPerformanceTimeOrigin!) / 1000;
|
|
344
|
-
const endTimestamp = startTimestamp + measure.duration / 1000;
|
|
345
|
-
|
|
346
|
-
const transaction = getActiveTransaction();
|
|
347
|
-
const span = transaction?.startChild({
|
|
348
|
-
op: 'ui.ember.init',
|
|
349
|
-
startTimestamp,
|
|
350
|
-
});
|
|
351
|
-
span?.finish(endTimestamp);
|
|
352
|
-
performance.clearMarks(startName);
|
|
353
|
-
performance.clearMarks(endName);
|
|
354
|
-
|
|
355
|
-
performance.clearMeasures(measureName);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
export async function instrumentForPerformance(appInstance: ApplicationInstance) {
|
|
359
|
-
const config = getSentryConfig();
|
|
360
|
-
const sentryConfig = config.sentry;
|
|
361
|
-
// Maintaining backwards compatibility with config.browserTracingOptions, but passing it with Sentry options is preferred.
|
|
362
|
-
const browserTracingOptions = config.browserTracingOptions || config.sentry.browserTracingOptions || {};
|
|
363
|
-
|
|
364
|
-
const tracing = await import('@sentry/tracing');
|
|
365
|
-
|
|
366
|
-
const idleTimeout = config.transitionTimeout || 5000;
|
|
367
|
-
|
|
368
|
-
const existingIntegrations = (sentryConfig['integrations'] || []) as Integration[];
|
|
369
|
-
|
|
370
|
-
sentryConfig['integrations'] = [
|
|
371
|
-
...existingIntegrations,
|
|
372
|
-
new tracing.Integrations.BrowserTracing({
|
|
373
|
-
routingInstrumentation: (customStartTransaction, startTransactionOnPageLoad) => {
|
|
374
|
-
const routerMain = appInstance.lookup('router:main');
|
|
375
|
-
const routerService = appInstance.lookup('service:router');
|
|
376
|
-
_instrumentEmberRouter(routerService, routerMain, config, customStartTransaction, startTransactionOnPageLoad);
|
|
377
|
-
},
|
|
378
|
-
idleTimeout,
|
|
379
|
-
...browserTracingOptions,
|
|
380
|
-
}),
|
|
381
|
-
];
|
|
382
|
-
|
|
383
|
-
class FakeBrowserTracingClass {
|
|
384
|
-
static id = tracing.BROWSER_TRACING_INTEGRATION_ID;
|
|
385
|
-
public name = FakeBrowserTracingClass.id;
|
|
386
|
-
setupOnce() {
|
|
387
|
-
// noop - We're just faking this class for a lookup
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
if (
|
|
392
|
-
isTesting() &&
|
|
393
|
-
Sentry.getCurrentHub()?.getIntegration(
|
|
394
|
-
// This is a temporary hack because the BrowserTracing integration cannot have a static `id` field for tree
|
|
395
|
-
// shaking reasons. However, `getIntegration` needs that field.
|
|
396
|
-
FakeBrowserTracingClass,
|
|
397
|
-
)
|
|
398
|
-
) {
|
|
399
|
-
// Initializers are called more than once in tests, causing the integrations to not be setup correctly.
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
Sentry.init(sentryConfig); // Call init again to rebind client with new integration list in addition to the defaults
|
|
404
|
-
|
|
405
|
-
_instrumentEmberRunloop(config);
|
|
406
|
-
_instrumentComponents(config);
|
|
407
|
-
_instrumentInitialLoad(config);
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
export default {
|
|
411
|
-
initialize,
|
|
412
|
-
};
|
package/addon/runloop.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { Backburner } from '@ember/runloop/-private/backburner';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Backburner needs to be extended as it's missing the 'off' method.
|
|
5
|
-
*/
|
|
6
|
-
interface ExtendedBackburner extends Backburner {
|
|
7
|
-
off(...args: any[]): void;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Runloop needs to be extended to expose backburner as suggested here:
|
|
12
|
-
* https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/ember__runloop/ember__runloop-tests.ts#L9
|
|
13
|
-
*/
|
|
14
|
-
declare module '@ember/runloop' {
|
|
15
|
-
interface RunNamespace {
|
|
16
|
-
backburner?: ExtendedBackburner;
|
|
17
|
-
}
|
|
18
|
-
export const _backburner: ExtendedBackburner; // Ember 4.0
|
|
19
|
-
}
|
package/addon/types.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { BrowserOptions } from '@sentry/browser';
|
|
2
|
-
|
|
3
|
-
export type EmberSentryConfig = {
|
|
4
|
-
sentry: BrowserOptions & { browserTracingOptions: Object };
|
|
5
|
-
transitionTimeout: number;
|
|
6
|
-
ignoreEmberOnErrorWarning: boolean;
|
|
7
|
-
disableInstrumentComponents: boolean;
|
|
8
|
-
disablePerformance: boolean;
|
|
9
|
-
disablePostTransitionRender: boolean;
|
|
10
|
-
disableRunloopPerformance: boolean;
|
|
11
|
-
disableInitialLoadInstrumentation: boolean;
|
|
12
|
-
enableComponentDefinitions: boolean;
|
|
13
|
-
minimumRunloopQueueDuration: number;
|
|
14
|
-
minimumComponentRenderDuration: number;
|
|
15
|
-
browserTracingOptions: Object;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export type OwnConfig = {
|
|
19
|
-
sentryConfig: EmberSentryConfig;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export type GlobalConfig = {
|
|
23
|
-
__sentryEmberConfig: EmberSentryConfig['sentry'];
|
|
24
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default, initialize } from '@sentry/ember/instance-initializers/sentry-performance';
|
package/config/environment.js
DELETED
package/ember.d.ts
DELETED
package/index.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { BrowserOptions } from '@sentry/browser';
|
|
2
|
-
export declare function InitSentryForEmber(_runtimeConfig?: BrowserOptions): void;
|
|
3
|
-
export declare const getActiveTransaction: () => import("@sentry/types").Transaction | undefined;
|
|
4
|
-
export declare const instrumentRoutePerformance: (BaseRoute: any) => {
|
|
5
|
-
new (): {
|
|
6
|
-
[x: string]: any;
|
|
7
|
-
beforeModel(...args: any[]): Promise<any>;
|
|
8
|
-
model(...args: any[]): Promise<any>;
|
|
9
|
-
afterModel(...args: any[]): Promise<any>;
|
|
10
|
-
setupController(...args: any[]): Promise<any>;
|
|
11
|
-
};
|
|
12
|
-
[x: string]: any;
|
|
13
|
-
};
|
|
14
|
-
export * from '@sentry/browser';
|
|
15
|
-
export declare const init: typeof InitSentryForEmber;
|
package/index.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const crypto = require('crypto');
|
|
4
|
-
|
|
5
|
-
function readSnippet(fileName) {
|
|
6
|
-
return fs.readFileSync(`${__dirname}/vendor/${fileName}`, 'utf8');
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
function hashSha256base64(string) {
|
|
10
|
-
return crypto.createHash('sha256').update(string).digest('base64');
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const initialLoadHeadSnippet = readSnippet('initial-load-head.js');
|
|
14
|
-
const initialLoadBodySnippet = readSnippet('initial-load-body.js');
|
|
15
|
-
|
|
16
|
-
const initialLoadHeadSnippetHash = hashSha256base64(initialLoadHeadSnippet);
|
|
17
|
-
const initialLoadBodySnippetHash = hashSha256base64(initialLoadBodySnippet);
|
|
18
|
-
|
|
19
|
-
module.exports = {
|
|
20
|
-
name: require('./package').name,
|
|
21
|
-
options: {
|
|
22
|
-
babel: {
|
|
23
|
-
plugins: [require.resolve('ember-auto-import/babel-plugin')],
|
|
24
|
-
},
|
|
25
|
-
'@embroider/macros': {
|
|
26
|
-
setOwnConfig: {},
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
config(_, appConfig) {
|
|
31
|
-
const addonConfig = appConfig['@sentry/ember'];
|
|
32
|
-
this.options['@embroider/macros'].setOwnConfig.sentryConfig = { ...addonConfig };
|
|
33
|
-
return this._super(...arguments);
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
contentFor(type, config) {
|
|
37
|
-
const addonConfig = config['@sentry/ember'] || {};
|
|
38
|
-
const { disablePerformance, disableInitialLoadInstrumentation } = addonConfig;
|
|
39
|
-
|
|
40
|
-
if (disablePerformance || disableInitialLoadInstrumentation) {
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (type === 'head') {
|
|
45
|
-
return `<script type="text/javascript">${initialLoadHeadSnippet}</script>`;
|
|
46
|
-
} else if (type === 'body-footer') {
|
|
47
|
-
return `<script type="text/javascript">${initialLoadBodySnippet}</script>`;
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
|
|
51
|
-
injectedScriptHashes: [initialLoadHeadSnippetHash, initialLoadBodySnippetHash],
|
|
52
|
-
};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import ApplicationInstance from '@ember/application/instance';
|
|
2
|
-
import { EmberSentryConfig } from '../types';
|
|
3
|
-
export declare function initialize(appInstance: ApplicationInstance): void;
|
|
4
|
-
export declare function _instrumentEmberRouter(routerService: any, routerMain: any, config: EmberSentryConfig, startTransaction: Function, startTransactionOnPageLoad?: boolean): {
|
|
5
|
-
startTransaction: Function;
|
|
6
|
-
};
|
|
7
|
-
export declare function instrumentForPerformance(appInstance: ApplicationInstance): Promise<void>;
|
|
8
|
-
declare const _default: {
|
|
9
|
-
initialize: typeof initialize;
|
|
10
|
-
};
|
|
11
|
-
export default _default;
|
package/runloop.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { Backburner } from '@ember/runloop/-private/backburner';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Backburner needs to be extended as it's missing the 'off' method.
|
|
5
|
-
*/
|
|
6
|
-
interface ExtendedBackburner extends Backburner {
|
|
7
|
-
off(...args: any[]): void;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Runloop needs to be extended to expose backburner as suggested here:
|
|
12
|
-
* https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/ember__runloop/ember__runloop-tests.ts#L9
|
|
13
|
-
*/
|
|
14
|
-
declare module '@ember/runloop' {
|
|
15
|
-
interface RunNamespace {
|
|
16
|
-
backburner?: ExtendedBackburner;
|
|
17
|
-
}
|
|
18
|
-
export const _backburner: ExtendedBackburner; // Ember 4.0
|
|
19
|
-
}
|
package/scripts/run-CI-tests.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/*eslint-env node*/
|
|
2
|
-
const { spawnSync } = require('child_process');
|
|
3
|
-
|
|
4
|
-
console.log('Mimicking the CI environment in order to run tests against multiple versions of Ember');
|
|
5
|
-
|
|
6
|
-
const result = spawnSync('yarn test', {
|
|
7
|
-
shell: true,
|
|
8
|
-
stdio: 'inherit',
|
|
9
|
-
env: {
|
|
10
|
-
...process.env,
|
|
11
|
-
GITHUB_ACTIONS: true,
|
|
12
|
-
GITHUB_EVENT_NAME: 'push',
|
|
13
|
-
GITHUB_HEAD_REF: 'master',
|
|
14
|
-
},
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
process.exit(result.status);
|
package/tsconfig.json
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "../../tsconfig.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"target": "es2017",
|
|
5
|
-
"allowJs": true,
|
|
6
|
-
"moduleResolution": "node",
|
|
7
|
-
"allowSyntheticDefaultImports": true,
|
|
8
|
-
"alwaysStrict": true,
|
|
9
|
-
"noImplicitUseStrict": false,
|
|
10
|
-
"strictNullChecks": true,
|
|
11
|
-
"strictPropertyInitialization": true,
|
|
12
|
-
"noEmitOnError": false,
|
|
13
|
-
"noEmit": true,
|
|
14
|
-
"baseUrl": ".",
|
|
15
|
-
"module": "esnext",
|
|
16
|
-
"experimentalDecorators": true,
|
|
17
|
-
"paths": {
|
|
18
|
-
"dummy/tests/*": ["tests/*"],
|
|
19
|
-
"dummy/*": ["tests/dummy/app/*", "app/*"],
|
|
20
|
-
"@sentry/ember": ["addon"],
|
|
21
|
-
"@sentry/ember/*": ["addon/*"],
|
|
22
|
-
"@sentry/ember/test-support": ["addon-test-support"],
|
|
23
|
-
"@sentry/ember/test-support/*": ["addon-test-support/*"],
|
|
24
|
-
"*": ["types/*"]
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
"include": ["app/**/*", "addon/**/*", "types/**/*", "addon-test-support/**/*"]
|
|
28
|
-
}
|
package/types.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { BrowserOptions } from '@sentry/browser';
|
|
2
|
-
export declare type EmberSentryConfig = {
|
|
3
|
-
sentry: BrowserOptions & {
|
|
4
|
-
browserTracingOptions: Object;
|
|
5
|
-
};
|
|
6
|
-
transitionTimeout: number;
|
|
7
|
-
ignoreEmberOnErrorWarning: boolean;
|
|
8
|
-
disableInstrumentComponents: boolean;
|
|
9
|
-
disablePerformance: boolean;
|
|
10
|
-
disablePostTransitionRender: boolean;
|
|
11
|
-
disableRunloopPerformance: boolean;
|
|
12
|
-
disableInitialLoadInstrumentation: boolean;
|
|
13
|
-
enableComponentDefinitions: boolean;
|
|
14
|
-
minimumRunloopQueueDuration: number;
|
|
15
|
-
minimumComponentRenderDuration: number;
|
|
16
|
-
browserTracingOptions: Object;
|
|
17
|
-
};
|
|
18
|
-
export declare type OwnConfig = {
|
|
19
|
-
sentryConfig: EmberSentryConfig;
|
|
20
|
-
};
|
|
21
|
-
export declare type GlobalConfig = {
|
|
22
|
-
__sentryEmberConfig: EmberSentryConfig['sentry'];
|
|
23
|
-
};
|