-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
Copy pathindex.ts
134 lines (115 loc) · 4.45 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import { assert, warn } from '@ember/debug';
import type Route from '@ember/routing/route';
import { next } from '@ember/runloop';
import { getOwnConfig, isDevelopingApp, macroCondition } from '@embroider/macros';
import { startSpan } from '@sentry/browser';
import type { BrowserOptions } from '@sentry/browser';
import * as Sentry from '@sentry/browser';
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, applySdkMetadata } from '@sentry/core';
import { GLOBAL_OBJ } from '@sentry/core';
import Ember from 'ember';
import type { Client, TransactionSource } from '@sentry/core';
import type { EmberSentryConfig, GlobalConfig, OwnConfig } from './types';
function _getSentryInitConfig(): EmberSentryConfig['sentry'] {
const _global = GLOBAL_OBJ as typeof GLOBAL_OBJ & GlobalConfig;
_global.__sentryEmberConfig = _global.__sentryEmberConfig ?? {};
return _global.__sentryEmberConfig;
}
/**
* Initialize the Sentry SDK for Ember.
*/
export function init(_runtimeConfig?: BrowserOptions): Client | undefined {
const environmentConfig = getOwnConfig<OwnConfig>().sentryConfig;
assert('Missing configuration.', environmentConfig);
assert('Missing configuration for Sentry.', environmentConfig.sentry || _runtimeConfig);
if (!environmentConfig.sentry) {
// If environment config is not specified but the above assertion passes, use runtime config.
environmentConfig.sentry = { ..._runtimeConfig };
}
// Merge runtime config into environment config, preferring runtime.
Object.assign(environmentConfig.sentry, _runtimeConfig || {});
const initConfig = Object.assign({}, environmentConfig.sentry);
applySdkMetadata(initConfig, 'ember');
// Persist Sentry init options so they are identical when performance initializers call init again.
const sentryInitConfig = _getSentryInitConfig();
Object.assign(sentryInitConfig, initConfig);
const client = Sentry.init(initConfig);
if (macroCondition(isDevelopingApp())) {
if (environmentConfig.ignoreEmberOnErrorWarning) {
return client;
}
next(null, function () {
warn(
'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.',
!Ember.onerror,
{
id: '@sentry/ember.ember-onerror-detected',
},
);
});
}
return client;
}
type RouteConstructor = new (...args: ConstructorParameters<typeof Route>) => Route;
export const instrumentRoutePerformance = <T extends RouteConstructor>(BaseRoute: T): T => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const instrumentFunction = async <X extends (...args: unknown[]) => any>(
op: string,
name: string,
fn: X,
args: Parameters<X>,
source: TransactionSource,
): Promise<ReturnType<X>> => {
return startSpan(
{
attributes: {
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.ember',
},
op,
name,
onlyIfParent: true,
},
() => {
return fn(...args);
},
);
};
const routeName = BaseRoute.name;
return {
// @ts-expect-error TS2545 We do not need to redefine a constructor here
[routeName]: class extends BaseRoute {
public beforeModel(...args: unknown[]): void | Promise<unknown> {
return instrumentFunction(
'ui.ember.route.before_model',
this.fullRouteName,
super.beforeModel.bind(this),
args,
'custom',
);
}
public async model(...args: unknown[]): Promise<unknown> {
return instrumentFunction('ui.ember.route.model', this.fullRouteName, super.model.bind(this), args, 'custom');
}
public afterModel(...args: unknown[]): void | Promise<unknown> {
return instrumentFunction(
'ui.ember.route.after_model',
this.fullRouteName,
super.afterModel.bind(this),
args,
'custom',
);
}
public setupController(...args: unknown[]): void | Promise<unknown> {
return instrumentFunction(
'ui.ember.route.setup_controller',
this.fullRouteName,
super.setupController.bind(this),
args,
'custom',
);
}
},
}[routeName] as T;
};
export * from '@sentry/browser';