Skip to content

Commit bb6f865

Browse files
authored
ref(node): Refactor node stack parsing to use common parser (#4612)
- Converts the node stack parser to be line orientated and return `StackFrame | undefined` - Uses the common parser from `@sentry/utils` - Updates the tests to cater for this - `StackFrame[]` are reversed - Additional fields added
1 parent 0d9883d commit bb6f865

File tree

8 files changed

+342
-498
lines changed

8 files changed

+342
-498
lines changed

packages/node/src/backend.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { BaseBackend } from '@sentry/core';
22
import { Event, EventHint, Severity, Transport, TransportOptions } from '@sentry/types';
3-
import { makeDsn } from '@sentry/utils';
3+
import { makeDsn, resolvedSyncPromise } from '@sentry/utils';
44

5-
import { eventFromException, eventFromMessage } from './eventbuilder';
5+
import { eventFromError, eventFromMessage } from './eventbuilder';
66
import { HTTPSTransport, HTTPTransport } from './transports';
77
import { NodeOptions } from './types';
88

@@ -16,14 +16,14 @@ export class NodeBackend extends BaseBackend<NodeOptions> {
1616
*/
1717
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
1818
public eventFromException(exception: any, hint?: EventHint): PromiseLike<Event> {
19-
return eventFromException(exception, hint);
19+
return resolvedSyncPromise(eventFromError(exception, hint));
2020
}
2121

2222
/**
2323
* @inheritDoc
2424
*/
2525
public eventFromMessage(message: string, level: Severity = Severity.Info, hint?: EventHint): PromiseLike<Event> {
26-
return eventFromMessage(this._options, message, level, hint);
26+
return resolvedSyncPromise(eventFromMessage(this._options, message, level, hint));
2727
}
2828

2929
/**

packages/node/src/eventbuilder.ts

+48-28
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,46 @@
11
import { getCurrentHub } from '@sentry/hub';
2-
import { Event, EventHint, Mechanism, Options, Severity } from '@sentry/types';
2+
import { Event, EventHint, Exception, Mechanism, Options, Severity, StackFrame } from '@sentry/types';
33
import {
44
addExceptionMechanism,
55
addExceptionTypeValue,
6+
createStackParser,
67
extractExceptionKeysForMessage,
78
isError,
89
isPlainObject,
910
normalizeToSize,
10-
SyncPromise,
1111
} from '@sentry/utils';
1212

13-
import { extractStackFromError, parseError, parseStack, prepareFramesForEvent } from './parsers';
13+
import { nodeStackParser } from './stack-parser';
14+
15+
/**
16+
* Extracts stack frames from the error.stack string
17+
*/
18+
export function extractStackFromError(error: Error): StackFrame[] {
19+
return createStackParser(nodeStackParser)(error.stack || '');
20+
}
21+
22+
/**
23+
* Extracts stack frames from the error and builds a Sentry Exception
24+
*/
25+
export function exceptionFromError(error: Error): Exception {
26+
const exception: Exception = {
27+
type: error.name || error.constructor.name,
28+
value: error.message,
29+
};
30+
31+
const frames = extractStackFromError(error);
32+
if (frames.length) {
33+
exception.stacktrace = { frames };
34+
}
35+
36+
return exception;
37+
}
1438

1539
/**
1640
* Builds and Event from a Exception
1741
* @hidden
1842
*/
19-
export function eventFromException(exception: unknown, hint?: EventHint): PromiseLike<Event> {
43+
export function eventFromError(exception: unknown, hint?: EventHint): Event {
2044
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2145
let ex: any = exception;
2246
const providedMechanism: Mechanism | undefined =
@@ -47,19 +71,19 @@ export function eventFromException(exception: unknown, hint?: EventHint): Promis
4771
mechanism.synthetic = true;
4872
}
4973

50-
return new SyncPromise<Event>((resolve, reject) =>
51-
parseError(ex as Error)
52-
.then(event => {
53-
addExceptionTypeValue(event, undefined, undefined);
54-
addExceptionMechanism(event, mechanism);
74+
const event = {
75+
exception: {
76+
values: [exceptionFromError(ex as Error)],
77+
},
78+
};
5579

56-
resolve({
57-
...event,
58-
event_id: hint && hint.event_id,
59-
});
60-
})
61-
.then(null, reject),
62-
);
80+
addExceptionTypeValue(event, undefined, undefined);
81+
addExceptionMechanism(event, mechanism);
82+
83+
return {
84+
...event,
85+
event_id: hint && hint.event_id,
86+
};
6387
}
6488

6589
/**
@@ -71,23 +95,19 @@ export function eventFromMessage(
7195
message: string,
7296
level: Severity = Severity.Info,
7397
hint?: EventHint,
74-
): PromiseLike<Event> {
98+
): Event {
7599
const event: Event = {
76100
event_id: hint && hint.event_id,
77101
level,
78102
message,
79103
};
80104

81-
return new SyncPromise<Event>(resolve => {
82-
if (options.attachStacktrace && hint && hint.syntheticException) {
83-
const stack = hint.syntheticException ? extractStackFromError(hint.syntheticException) : [];
84-
const frames = parseStack(stack);
85-
event.stacktrace = {
86-
frames: prepareFramesForEvent(frames),
87-
};
88-
resolve(event);
89-
} else {
90-
resolve(event);
105+
if (options.attachStacktrace && hint && hint.syntheticException) {
106+
const frames = extractStackFromError(hint.syntheticException);
107+
if (frames.length) {
108+
event.stacktrace = { frames };
91109
}
92-
});
110+
}
111+
112+
return event;
93113
}

packages/node/src/integrations/linkederrors.ts

+6-9
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { addGlobalEventProcessor, getCurrentHub } from '@sentry/core';
22
import { Event, EventHint, Exception, ExtendedError, Integration } from '@sentry/types';
33
import { isInstanceOf, resolvedSyncPromise, SyncPromise } from '@sentry/utils';
44

5-
import { getExceptionFromError } from '../parsers';
5+
import { exceptionFromError } from '../eventbuilder';
66

77
const DEFAULT_KEY = 'cause';
88
const DEFAULT_LIMIT = 5;
@@ -80,15 +80,12 @@ export class LinkedErrors implements Integration {
8080
if (!isInstanceOf(error[key], Error) || stack.length + 1 >= this._limit) {
8181
return resolvedSyncPromise(stack);
8282
}
83+
84+
const exception = exceptionFromError(error[key]);
85+
8386
return new SyncPromise<Exception[]>((resolve, reject) => {
84-
void getExceptionFromError(error[key])
85-
.then((exception: Exception) => {
86-
void this._walkErrorTree(error[key], key, [exception, ...stack])
87-
.then(resolve)
88-
.then(null, () => {
89-
reject();
90-
});
91-
})
87+
void this._walkErrorTree(error[key], key, [exception, ...stack])
88+
.then(resolve)
9289
.then(null, () => {
9390
reject();
9491
});

packages/node/src/parsers.ts

-148
This file was deleted.

0 commit comments

Comments
 (0)