-
-
Notifications
You must be signed in to change notification settings - Fork 58
/
Copy pathnormalize.ts
101 lines (89 loc) · 3.01 KB
/
normalize.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
import { Event, Exception, Stacktrace } from '@sentry/types';
/**
* Normalizes URLs in exceptions and stacktraces so Sentry can fingerprint
* across platforms.
*
* @param url The URL to be normalized.
* @param basePath The application base path.
* @returns The normalized URL.
*/
export function normalizeUrl(url: string, basePath: string): string {
const escapedBase = basePath
// Backslash to forward
.replace(/\\/g, '/')
// Escape RegExp special characters
.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&');
let newUrl = url;
try {
newUrl = decodeURI(url);
} catch (_Oo) {
// Sometime this breaks
}
return newUrl
.replace(/\\/g, '/')
.replace(/webpack:\/?/g, '') // Remove intermediate base path
.replace(new RegExp(`(file://)?/*${escapedBase}/*`, 'ig'), 'app:///');
}
/**
* Normalizes all URLs in an event. See {@link normalizeUrl} for more
* information. Mutates the passed in event.
*
* @param event The event to normalize.
*/
export function normalizeEvent(event: Event, basePath: string): Event {
// Retrieve stack traces and normalize their URLs. Without this, grouping
// would not work due to user folders in file names.
const stacktrace = getStacktrace(event);
if (stacktrace && stacktrace.frames) {
stacktrace.frames.forEach((frame) => {
if (frame.filename) {
frame.filename = normalizeUrl(frame.filename, basePath);
}
});
}
if (event.transaction) {
event.transaction = normalizeUrl(event.transaction, basePath);
}
const { request = {} } = event;
if (request.url) {
request.url = normalizeUrl(request.url, basePath);
}
// The user agent is parsed by Sentry and would overwrite certain context
// information, which we don't want. Generally remove it, since we know that
// we are browsing with Chrome.
if (request.headers) {
delete request.headers['User-Agent'];
}
// The Node SDK currently adds a default tag for server_name, which contains
// the machine name of the computer running Electron. This is not useful
// information in this case.
const { tags = {} } = event;
delete tags.server_name;
return event;
}
/**
* Returns a reference to the exception stack trace in the given event.
* @param event An event potentially containing stack traces.
*/
function getStacktrace(event: Event): Stacktrace | undefined {
const { stacktrace, exception } = event;
// Try the main event stack trace first
if (stacktrace) {
return stacktrace;
}
if (exception) {
// Raven Node adheres to the Event interface
// @ts-ignore: need to be able to index exception
if (exception[0]) {
// @ts-ignore: need to be able to index exception
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
return exception[0].stacktrace;
}
// Raven JS uses the full values interface, which has been removed
const raven = exception as any as { values: Exception[] };
if (raven.values && raven.values[0]) {
return raven.values[0].stacktrace;
}
}
return undefined;
}