UNPKG

3.48 kBJavaScriptView Raw
1import { isError, normalize, isPlainObject, addNonEnumerableProperty, logger } from '@sentry/utils';
2
3/** JSDoc */
4
5/** Patch toString calls to return proper name for wrapped functions */
6class ExtraErrorData {
7 /**
8 * @inheritDoc
9 */
10 static __initStatic() {this.id = 'ExtraErrorData';}
11
12 /**
13 * @inheritDoc
14 */
15 __init() {this.name = ExtraErrorData.id;}
16
17 /** JSDoc */
18
19 /**
20 * @inheritDoc
21 */
22 constructor(options) {ExtraErrorData.prototype.__init.call(this);
23 this._options = {
24 depth: 3,
25 ...options,
26 };
27 }
28
29 /**
30 * @inheritDoc
31 */
32 setupOnce(addGlobalEventProcessor, getCurrentHub) {
33 addGlobalEventProcessor((event, hint) => {
34 const self = getCurrentHub().getIntegration(ExtraErrorData);
35 if (!self) {
36 return event;
37 }
38 return self.enhanceEventWithErrorData(event, hint);
39 });
40 }
41
42 /**
43 * Attaches extracted information from the Error object to extra field in the Event
44 */
45 enhanceEventWithErrorData(event, hint = {}) {
46 if (!hint.originalException || !isError(hint.originalException)) {
47 return event;
48 }
49 const exceptionName = (hint.originalException ).name || hint.originalException.constructor.name;
50
51 const errorData = this._extractErrorData(hint.originalException );
52
53 if (errorData) {
54 const contexts = {
55 ...event.contexts,
56 };
57
58 const normalizedErrorData = normalize(errorData, this._options.depth);
59
60 if (isPlainObject(normalizedErrorData)) {
61 // We mark the error data as "already normalized" here, because we don't want other normalization procedures to
62 // potentially truncate the data we just already normalized, with a certain depth setting.
63 addNonEnumerableProperty(normalizedErrorData, '__sentry_skip_normalization__', true);
64 contexts[exceptionName] = normalizedErrorData;
65 }
66
67 return {
68 ...event,
69 contexts,
70 };
71 }
72
73 return event;
74 }
75
76 /**
77 * Extract extra information from the Error object
78 */
79 _extractErrorData(error) {
80 // We are trying to enhance already existing event, so no harm done if it won't succeed
81 try {
82 const nativeKeys = [
83 'name',
84 'message',
85 'stack',
86 'line',
87 'column',
88 'fileName',
89 'lineNumber',
90 'columnNumber',
91 'toJSON',
92 ];
93
94 const extraErrorInfo = {};
95
96 // We want only enumerable properties, thus `getOwnPropertyNames` is redundant here, as we filter keys anyway.
97 for (const key of Object.keys(error)) {
98 if (nativeKeys.indexOf(key) !== -1) {
99 continue;
100 }
101 const value = error[key];
102 extraErrorInfo[key] = isError(value) ? value.toString() : value;
103 }
104
105 // Check if someone attached `toJSON` method to grab even more properties (eg. axios is doing that)
106 if (typeof error.toJSON === 'function') {
107 const serializedError = error.toJSON() ;
108
109 for (const key of Object.keys(serializedError)) {
110 const value = serializedError[key];
111 extraErrorInfo[key] = isError(value) ? value.toString() : value;
112 }
113 }
114
115 return extraErrorInfo;
116 } catch (oO) {
117 (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.error('Unable to extract extra data from the Error object:', oO);
118 }
119
120 return null;
121 }
122} ExtraErrorData.__initStatic();
123
124export { ExtraErrorData };
125//# sourceMappingURL=extraerrordata.js.map