@book000/node-utils 1.25.171 → 1.25.173
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/README.md +2 -0
- package/dist/__tests__/sentry-transport.test.js +96 -30
- package/dist/__tests__/sentry-transport.test.js.map +1 -1
- package/dist/sentry-transport.d.ts +2 -0
- package/dist/sentry-transport.d.ts.map +1 -1
- package/dist/sentry-transport.js +64 -9
- package/dist/sentry-transport.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -87,6 +87,8 @@ const logger = Logger.configure('main')
|
|
|
87
87
|
logger.error('Something went wrong', new Error('boom'))
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
+
The forwarded issue keeps the original error's name and message as its title, and the log message (`'Something went wrong'`) is attached as the `log.message` tag. Issues are grouped by a fingerprint of the level, error name, and first application stack frame (function and file name), or by the message for logs without an `Error`. Logging an error and then rethrowing it still reports it twice.
|
|
91
|
+
|
|
90
92
|
| Environment variable | Required | Default | Description |
|
|
91
93
|
|---|---|---|---|
|
|
92
94
|
| `SENTRY_DSN` | No (opt-in) | none | When unset, `SentryTransport` / `ErrorReporter` are fully no-op |
|
|
@@ -32,47 +32,125 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
35
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
39
|
const Sentry = __importStar(require("@sentry/node"));
|
|
40
|
+
const winston_1 = __importDefault(require("winston"));
|
|
37
41
|
const sentry_transport_1 = require("../sentry-transport");
|
|
38
42
|
const sentry_client_1 = require("../sentry/sentry-client");
|
|
43
|
+
const scope = {
|
|
44
|
+
setLevel: jest.fn(),
|
|
45
|
+
setTag: jest.fn(),
|
|
46
|
+
setFingerprint: jest.fn(),
|
|
47
|
+
};
|
|
39
48
|
jest.mock('@sentry/node', () => ({
|
|
40
49
|
captureException: jest.fn(),
|
|
41
|
-
|
|
50
|
+
captureEvent: jest.fn(),
|
|
51
|
+
withScope: jest.fn((callback) => {
|
|
52
|
+
callback(scope);
|
|
53
|
+
}),
|
|
42
54
|
flush: jest.fn().mockResolvedValue(true),
|
|
43
55
|
}));
|
|
44
56
|
jest.mock('../sentry/sentry-client', () => ({
|
|
45
57
|
ensureSentryInitialized: jest.fn(),
|
|
46
58
|
toSeverityLevel: jest.fn((level) => level === 'warn' ? 'warning' : level),
|
|
47
59
|
}));
|
|
60
|
+
function withStack(message, stack) {
|
|
61
|
+
const error = new Error(message);
|
|
62
|
+
Object.defineProperty(error, 'stack', { value: stack });
|
|
63
|
+
return error;
|
|
64
|
+
}
|
|
48
65
|
describe('SentryTransport', () => {
|
|
49
66
|
let transport;
|
|
50
67
|
beforeEach(() => {
|
|
51
68
|
jest.clearAllMocks();
|
|
52
|
-
transport = new sentry_transport_1.SentryTransport({
|
|
69
|
+
transport = new sentry_transport_1.SentryTransport({
|
|
70
|
+
dsn: 'https://example.com/1',
|
|
71
|
+
level: 'warn',
|
|
72
|
+
});
|
|
53
73
|
});
|
|
54
74
|
it('should call ensureSentryInitialized with the given options on construction', () => {
|
|
55
75
|
expect(sentry_client_1.ensureSentryInitialized).toHaveBeenCalledWith({
|
|
56
76
|
dsn: 'https://example.com/1',
|
|
77
|
+
level: 'warn',
|
|
57
78
|
});
|
|
58
79
|
});
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
80
|
+
describe('with the real winston Logger', () => {
|
|
81
|
+
const createLogger = () => winston_1.default.createLogger({
|
|
82
|
+
format: winston_1.default.format.errors({ stack: true }),
|
|
83
|
+
transports: [transport],
|
|
84
|
+
});
|
|
85
|
+
it('should capture the original Error and keep the log message out of the title', () => {
|
|
86
|
+
const error = new TypeError('inner');
|
|
87
|
+
createLogger().error('[Auth] failed:', error);
|
|
88
|
+
expect(Sentry.captureException).toHaveBeenCalledWith(expect.objectContaining({ name: 'TypeError', message: 'inner' }));
|
|
89
|
+
expect(scope.setTag).toHaveBeenCalledWith('log.message', '[Auth] failed: inner');
|
|
90
|
+
expect(scope.setFingerprint).toHaveBeenCalledWith([
|
|
91
|
+
'error',
|
|
92
|
+
'TypeError',
|
|
93
|
+
expect.stringMatching(/sentry-transport\.test\.ts$/),
|
|
94
|
+
]);
|
|
95
|
+
expect(Sentry.captureEvent).not.toHaveBeenCalled();
|
|
96
|
+
});
|
|
97
|
+
it.each([
|
|
98
|
+
[' at run (/srv/app/dist/main.js:10:5)', 'at run main.js'],
|
|
99
|
+
[' at /srv/app/dist/main.js:10:5', 'at main.js'],
|
|
100
|
+
[
|
|
101
|
+
String.raw ` at async run (C:\srv\app\dist\main.js:10:5)`,
|
|
102
|
+
'at async run main.js',
|
|
103
|
+
],
|
|
104
|
+
[' at new Foo (<anonymous>)', 'at new Foo <anonymous>'],
|
|
105
|
+
])('should reduce the stack frame %j to %j in the fingerprint', (frame, expected) => {
|
|
106
|
+
const error = withStack('frame', `Error: frame\n${frame}`);
|
|
107
|
+
createLogger().error('failed', error);
|
|
108
|
+
expect(scope.setFingerprint).toHaveBeenCalledWith([
|
|
109
|
+
'error',
|
|
110
|
+
'Error',
|
|
111
|
+
expected,
|
|
112
|
+
]);
|
|
113
|
+
});
|
|
114
|
+
it('should not take quadratic time on a very long frame', () => {
|
|
115
|
+
const error = withStack('long', `Error: long\n at run (${'('.repeat(50000)}main.js:1:1)`);
|
|
116
|
+
const start = Date.now();
|
|
117
|
+
createLogger().error('failed', error);
|
|
118
|
+
expect(Date.now() - start).toBeLessThan(1000);
|
|
119
|
+
});
|
|
120
|
+
it('should capture the same Error instance every time it is logged', () => {
|
|
121
|
+
const error = new Error('again');
|
|
122
|
+
const logger = createLogger();
|
|
123
|
+
logger.warn('retry', error);
|
|
124
|
+
logger.error('gave up', error);
|
|
125
|
+
const calls = Sentry.captureException.mock.calls;
|
|
126
|
+
expect(calls).toHaveLength(2);
|
|
127
|
+
expect(calls[0]).not.toBe(error);
|
|
128
|
+
});
|
|
129
|
+
it('should rebuild the Error from stack when only logger.error(err) is used', () => {
|
|
130
|
+
createLogger().error(new RangeError('bad'));
|
|
131
|
+
expect(Sentry.captureException).toHaveBeenCalledWith(expect.objectContaining({ name: 'RangeError', message: 'bad' }));
|
|
132
|
+
});
|
|
133
|
+
it('should send a plain string error via captureEvent with a message fingerprint', () => {
|
|
134
|
+
createLogger().error('boom');
|
|
135
|
+
expect(Sentry.captureException).not.toHaveBeenCalled();
|
|
136
|
+
expect(Sentry.captureEvent).toHaveBeenCalledWith({
|
|
62
137
|
message: 'boom',
|
|
63
|
-
|
|
64
|
-
})
|
|
65
|
-
|
|
138
|
+
level: 'error',
|
|
139
|
+
});
|
|
140
|
+
expect(scope.setFingerprint).toHaveBeenCalledWith(['error', 'boom']);
|
|
66
141
|
});
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
142
|
+
it('should send a warn string via captureEvent with warning level', () => {
|
|
143
|
+
createLogger().warn('careful');
|
|
144
|
+
expect(Sentry.captureEvent).toHaveBeenCalledWith({
|
|
145
|
+
message: 'careful',
|
|
146
|
+
level: 'warning',
|
|
147
|
+
});
|
|
148
|
+
expect(scope.setFingerprint).toHaveBeenCalledWith(['warn', 'careful']);
|
|
149
|
+
});
|
|
150
|
+
it('should not capture levels below the transport level', () => {
|
|
151
|
+
createLogger().info('hello');
|
|
152
|
+
expect(Sentry.captureException).not.toHaveBeenCalled();
|
|
153
|
+
expect(Sentry.captureEvent).not.toHaveBeenCalled();
|
|
76
154
|
});
|
|
77
155
|
});
|
|
78
156
|
it('should emit an "error" event when Sentry.flush rejects', async () => {
|
|
@@ -87,17 +165,6 @@ describe('SentryTransport', () => {
|
|
|
87
165
|
expect(onError).toHaveBeenCalledWith(expect.any(Error));
|
|
88
166
|
expect(callback).toHaveBeenCalled();
|
|
89
167
|
});
|
|
90
|
-
it('should call captureMessage with "error" severity when level is error and no stack', (done) => {
|
|
91
|
-
transport.log({ level: 'error', message: 'boom' }, () => {
|
|
92
|
-
expect(Sentry.captureMessage).toHaveBeenCalledWith('boom', 'error');
|
|
93
|
-
done();
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
it('should call captureMessage with "warning" severity when level is warn', () => {
|
|
97
|
-
const callback = jest.fn();
|
|
98
|
-
transport.log({ level: 'warn', message: 'careful' }, callback);
|
|
99
|
-
expect(Sentry.captureMessage).toHaveBeenCalledWith('careful', 'warning');
|
|
100
|
-
});
|
|
101
168
|
it('should await Sentry.flush before invoking callback for error level', async () => {
|
|
102
169
|
const callback = jest.fn();
|
|
103
170
|
transport.log({ level: 'error', message: 'boom' }, callback);
|
|
@@ -113,10 +180,9 @@ describe('SentryTransport', () => {
|
|
|
113
180
|
expect(Sentry.flush).not.toHaveBeenCalled();
|
|
114
181
|
expect(callback).toHaveBeenCalled();
|
|
115
182
|
});
|
|
116
|
-
it('should not call captureException or
|
|
183
|
+
it('should not call captureException or captureEvent for info level', () => {
|
|
117
184
|
transport.log({ level: 'info', message: 'hello' }, jest.fn());
|
|
118
185
|
expect(Sentry.captureException).not.toHaveBeenCalled();
|
|
119
|
-
expect(Sentry.captureMessage).not.toHaveBeenCalled();
|
|
120
186
|
});
|
|
121
187
|
});
|
|
122
188
|
//# sourceMappingURL=sentry-transport.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sentry-transport.test.js","sourceRoot":"","sources":["../../src/__tests__/sentry-transport.test.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sentry-transport.test.js","sourceRoot":"","sources":["../../src/__tests__/sentry-transport.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,8 @@ export interface SentryTransportOptions extends TransportStream.TransportStreamO
|
|
|
6
6
|
export declare class SentryTransport extends TransportStream {
|
|
7
7
|
constructor(options: SentryTransportOptions);
|
|
8
8
|
log(info: Record<string, unknown>, callback: () => void): void;
|
|
9
|
+
private capture;
|
|
10
|
+
private findError;
|
|
9
11
|
private toError;
|
|
10
12
|
}
|
|
11
13
|
//# sourceMappingURL=sentry-transport.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sentry-transport.d.ts","sourceRoot":"","sources":["../src/sentry-transport.ts"],"names":[],"mappings":"AACA,OAAO,eAAe,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"sentry-transport.d.ts","sourceRoot":"","sources":["../src/sentry-transport.ts"],"names":[],"mappings":"AACA,OAAO,eAAe,MAAM,mBAAmB,CAAA;AA2C/C,MAAM,WAAW,sBACf,SAAQ,eAAe,CAAC,sBAAsB;IAC9C,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAOD,qBAAa,eAAgB,SAAQ,eAAe;gBACtC,OAAO,EAAE,sBAAsB;IAW3C,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAiC9D,OAAO,CAAC,OAAO;IAmCf,OAAO,CAAC,SAAS;IAWjB,OAAO,CAAC,OAAO;CAgBhB"}
|
package/dist/sentry-transport.js
CHANGED
|
@@ -40,6 +40,26 @@ exports.SentryTransport = void 0;
|
|
|
40
40
|
const Sentry = __importStar(require("@sentry/node"));
|
|
41
41
|
const winston_transport_1 = __importDefault(require("winston-transport"));
|
|
42
42
|
const sentry_client_1 = require("./sentry/sentry-client");
|
|
43
|
+
function firstAppFrame(error) {
|
|
44
|
+
const frame = error.stack
|
|
45
|
+
?.split('\n')
|
|
46
|
+
.find((line) => line.trimStart().startsWith('at ') &&
|
|
47
|
+
!line.includes('node_modules') &&
|
|
48
|
+
!line.includes('node:internal'))
|
|
49
|
+
?.trim();
|
|
50
|
+
if (frame === undefined) {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
const open = frame.endsWith(')') ? frame.lastIndexOf('(') : -1;
|
|
54
|
+
const prefix = open === -1 ? 'at ' : frame.slice(0, open);
|
|
55
|
+
const location = open === -1 ? frame.slice(3) : frame.slice(open + 1, -1);
|
|
56
|
+
const file = location.slice(Math.max(location.lastIndexOf('/'), location.lastIndexOf('\\')) + 1);
|
|
57
|
+
const parts = file.split(':');
|
|
58
|
+
const hasPosition = parts.length >= 3 &&
|
|
59
|
+
/^\d+$/.test(parts.at(-1) ?? '') &&
|
|
60
|
+
/^\d+$/.test(parts.at(-2) ?? '');
|
|
61
|
+
return prefix + (hasPosition ? parts.slice(0, -2).join(':') : file);
|
|
62
|
+
}
|
|
43
63
|
class SentryTransport extends winston_transport_1.default {
|
|
44
64
|
constructor(options) {
|
|
45
65
|
super(options);
|
|
@@ -49,11 +69,8 @@ class SentryTransport extends winston_transport_1.default {
|
|
|
49
69
|
setImmediate(() => this.emit('logged', info));
|
|
50
70
|
const { level, message, ...rest } = info;
|
|
51
71
|
const messageText = typeof message === 'string' ? message : String(message);
|
|
52
|
-
if (level === 'error'
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
else if (level === 'error' || level === 'warn') {
|
|
56
|
-
Sentry.captureMessage(messageText, (0, sentry_client_1.toSeverityLevel)(level));
|
|
72
|
+
if (level === 'error' || level === 'warn') {
|
|
73
|
+
this.capture(level, messageText, info, rest.stack);
|
|
57
74
|
}
|
|
58
75
|
if (level === 'error') {
|
|
59
76
|
Sentry.flush(2000)
|
|
@@ -67,12 +84,50 @@ class SentryTransport extends winston_transport_1.default {
|
|
|
67
84
|
}
|
|
68
85
|
callback();
|
|
69
86
|
}
|
|
70
|
-
|
|
87
|
+
capture(level, message, info, stack) {
|
|
88
|
+
const original = this.findError(info);
|
|
89
|
+
const error = original
|
|
90
|
+
? this.toError(original.message, original.stack ?? '', original.name)
|
|
91
|
+
: typeof stack === 'string'
|
|
92
|
+
? this.toError(message, stack)
|
|
93
|
+
: undefined;
|
|
94
|
+
Sentry.withScope((scope) => {
|
|
95
|
+
scope.setLevel((0, sentry_client_1.toSeverityLevel)(level));
|
|
96
|
+
scope.setTag('log.message', message);
|
|
97
|
+
if (error) {
|
|
98
|
+
scope.setFingerprint([
|
|
99
|
+
level,
|
|
100
|
+
error.name,
|
|
101
|
+
firstAppFrame(error) ?? error.message,
|
|
102
|
+
]);
|
|
103
|
+
Sentry.captureException(error);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
scope.setFingerprint([level, message]);
|
|
107
|
+
Sentry.captureEvent({ message, level: (0, sentry_client_1.toSeverityLevel)(level) });
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
findError(info) {
|
|
112
|
+
const splat = info[Symbol.for('splat')];
|
|
113
|
+
if (!Array.isArray(splat))
|
|
114
|
+
return undefined;
|
|
115
|
+
for (const arg of splat) {
|
|
116
|
+
if (arg instanceof Error)
|
|
117
|
+
return arg;
|
|
118
|
+
const nested = arg?.error;
|
|
119
|
+
if (nested instanceof Error)
|
|
120
|
+
return nested;
|
|
121
|
+
}
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
toError(message, stack, errorName) {
|
|
71
125
|
const error = new Error(message);
|
|
72
126
|
const firstLine = stack.split('\n', 1)[0];
|
|
73
|
-
const name =
|
|
74
|
-
|
|
75
|
-
|
|
127
|
+
const name = errorName ??
|
|
128
|
+
(firstLine.includes(': ')
|
|
129
|
+
? firstLine.slice(0, firstLine.indexOf(': '))
|
|
130
|
+
: undefined);
|
|
76
131
|
if (name) {
|
|
77
132
|
Object.defineProperty(error, 'name', { value: name, configurable: true });
|
|
78
133
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sentry-transport.js","sourceRoot":"","sources":["../src/sentry-transport.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qDAAsC;AACtC,0EAA+C;AAC/C,0DAG+B;
|
|
1
|
+
{"version":3,"file":"sentry-transport.js","sourceRoot":"","sources":["../src/sentry-transport.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@book000/node-utils",
|
|
3
|
-
"version": "1.25.
|
|
3
|
+
"version": "1.25.173",
|
|
4
4
|
"description": "Self-Utility library",
|
|
5
5
|
"homepage": "https://github.com/book000/node-utils",
|
|
6
6
|
"bugs": {
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"winston-transport": "4.9.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@book000/eslint-config": "1.16.
|
|
30
|
+
"@book000/eslint-config": "1.16.104",
|
|
31
31
|
"@types/jest": "30.0.0",
|
|
32
32
|
"@types/node": "25.9.9",
|
|
33
33
|
"ctix": "2.8.2",
|