@devmoods/sentry 0.5.0 → 0.5.1
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/coverage/clover.xml +3 -3
- package/coverage/coverage-final.json +1 -1
- package/coverage/index.html +1 -1
- package/coverage/index.ts.html +92 -5
- package/dist/index.js +15 -2
- package/package.json +5 -5
- package/src/__tests__/index.spec.ts +45 -0
- package/src/index.ts +31 -2
package/coverage/clover.xml
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<coverage generated="
|
|
3
|
-
<project timestamp="
|
|
2
|
+
<coverage generated="1783497115890" clover="3.2.0">
|
|
3
|
+
<project timestamp="1783497115890" name="All files">
|
|
4
4
|
<metrics statements="1" coveredstatements="1" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0" elements="1" coveredelements="1" complexity="0" loc="1" ncloc="1" packages="1" files="1" classes="1"/>
|
|
5
5
|
<file name="index.ts" path="/Users/hanse/dev/github.com/devmoods/express-extras/packages/@devmoods/sentry/src/index.ts">
|
|
6
6
|
<metrics statements="1" coveredstatements="1" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0"/>
|
|
7
|
-
<line num="14" count="
|
|
7
|
+
<line num="14" count="13" type="stmt"/>
|
|
8
8
|
</file>
|
|
9
9
|
</project>
|
|
10
10
|
</coverage>
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
{"/Users/hanse/dev/github.com/devmoods/express-extras/packages/@devmoods/sentry/src/index.ts": {"path":"/Users/hanse/dev/github.com/devmoods/express-extras/packages/@devmoods/sentry/src/index.ts","statementMap":{"0":{"start":{"line":14,"column":13},"end":{"line":19,"column":null}}},"fnMap":{},"branchMap":{},"s":{"0":
|
|
1
|
+
{"/Users/hanse/dev/github.com/devmoods/express-extras/packages/@devmoods/sentry/src/index.ts": {"path":"/Users/hanse/dev/github.com/devmoods/express-extras/packages/@devmoods/sentry/src/index.ts","statementMap":{"0":{"start":{"line":14,"column":13},"end":{"line":19,"column":null}}},"fnMap":{},"branchMap":{},"s":{"0":13},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":1,"seen":{"s:14:13:19:Infinity":0},"fnNames":{}}}
|
|
2
2
|
}
|
package/coverage/index.html
CHANGED
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
102
102
|
Code coverage generated by
|
|
103
103
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
104
|
-
at 2026-
|
|
104
|
+
at 2026-07-08T07:51:55.887Z
|
|
105
105
|
</div>
|
|
106
106
|
<script src="prettify.js"></script>
|
|
107
107
|
<script>
|
package/coverage/index.ts.html
CHANGED
|
@@ -241,7 +241,66 @@
|
|
|
241
241
|
<a name='L176'></a><a href='#L176'>176</a>
|
|
242
242
|
<a name='L177'></a><a href='#L177'>177</a>
|
|
243
243
|
<a name='L178'></a><a href='#L178'>178</a>
|
|
244
|
-
<a name='L179'></a><a href='#L179'>179</a
|
|
244
|
+
<a name='L179'></a><a href='#L179'>179</a>
|
|
245
|
+
<a name='L180'></a><a href='#L180'>180</a>
|
|
246
|
+
<a name='L181'></a><a href='#L181'>181</a>
|
|
247
|
+
<a name='L182'></a><a href='#L182'>182</a>
|
|
248
|
+
<a name='L183'></a><a href='#L183'>183</a>
|
|
249
|
+
<a name='L184'></a><a href='#L184'>184</a>
|
|
250
|
+
<a name='L185'></a><a href='#L185'>185</a>
|
|
251
|
+
<a name='L186'></a><a href='#L186'>186</a>
|
|
252
|
+
<a name='L187'></a><a href='#L187'>187</a>
|
|
253
|
+
<a name='L188'></a><a href='#L188'>188</a>
|
|
254
|
+
<a name='L189'></a><a href='#L189'>189</a>
|
|
255
|
+
<a name='L190'></a><a href='#L190'>190</a>
|
|
256
|
+
<a name='L191'></a><a href='#L191'>191</a>
|
|
257
|
+
<a name='L192'></a><a href='#L192'>192</a>
|
|
258
|
+
<a name='L193'></a><a href='#L193'>193</a>
|
|
259
|
+
<a name='L194'></a><a href='#L194'>194</a>
|
|
260
|
+
<a name='L195'></a><a href='#L195'>195</a>
|
|
261
|
+
<a name='L196'></a><a href='#L196'>196</a>
|
|
262
|
+
<a name='L197'></a><a href='#L197'>197</a>
|
|
263
|
+
<a name='L198'></a><a href='#L198'>198</a>
|
|
264
|
+
<a name='L199'></a><a href='#L199'>199</a>
|
|
265
|
+
<a name='L200'></a><a href='#L200'>200</a>
|
|
266
|
+
<a name='L201'></a><a href='#L201'>201</a>
|
|
267
|
+
<a name='L202'></a><a href='#L202'>202</a>
|
|
268
|
+
<a name='L203'></a><a href='#L203'>203</a>
|
|
269
|
+
<a name='L204'></a><a href='#L204'>204</a>
|
|
270
|
+
<a name='L205'></a><a href='#L205'>205</a>
|
|
271
|
+
<a name='L206'></a><a href='#L206'>206</a>
|
|
272
|
+
<a name='L207'></a><a href='#L207'>207</a>
|
|
273
|
+
<a name='L208'></a><a href='#L208'>208</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
|
274
|
+
<span class="cline-any cline-neutral"> </span>
|
|
275
|
+
<span class="cline-any cline-neutral"> </span>
|
|
276
|
+
<span class="cline-any cline-neutral"> </span>
|
|
277
|
+
<span class="cline-any cline-neutral"> </span>
|
|
278
|
+
<span class="cline-any cline-neutral"> </span>
|
|
279
|
+
<span class="cline-any cline-neutral"> </span>
|
|
280
|
+
<span class="cline-any cline-neutral"> </span>
|
|
281
|
+
<span class="cline-any cline-neutral"> </span>
|
|
282
|
+
<span class="cline-any cline-neutral"> </span>
|
|
283
|
+
<span class="cline-any cline-neutral"> </span>
|
|
284
|
+
<span class="cline-any cline-neutral"> </span>
|
|
285
|
+
<span class="cline-any cline-neutral"> </span>
|
|
286
|
+
<span class="cline-any cline-yes">13x</span>
|
|
287
|
+
<span class="cline-any cline-neutral"> </span>
|
|
288
|
+
<span class="cline-any cline-neutral"> </span>
|
|
289
|
+
<span class="cline-any cline-neutral"> </span>
|
|
290
|
+
<span class="cline-any cline-neutral"> </span>
|
|
291
|
+
<span class="cline-any cline-neutral"> </span>
|
|
292
|
+
<span class="cline-any cline-neutral"> </span>
|
|
293
|
+
<span class="cline-any cline-neutral"> </span>
|
|
294
|
+
<span class="cline-any cline-neutral"> </span>
|
|
295
|
+
<span class="cline-any cline-neutral"> </span>
|
|
296
|
+
<span class="cline-any cline-neutral"> </span>
|
|
297
|
+
<span class="cline-any cline-neutral"> </span>
|
|
298
|
+
<span class="cline-any cline-neutral"> </span>
|
|
299
|
+
<span class="cline-any cline-neutral"> </span>
|
|
300
|
+
<span class="cline-any cline-neutral"> </span>
|
|
301
|
+
<span class="cline-any cline-neutral"> </span>
|
|
302
|
+
<span class="cline-any cline-neutral"> </span>
|
|
303
|
+
<span class="cline-any cline-neutral"> </span>
|
|
245
304
|
<span class="cline-any cline-neutral"> </span>
|
|
246
305
|
<span class="cline-any cline-neutral"> </span>
|
|
247
306
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -254,7 +313,6 @@
|
|
|
254
313
|
<span class="cline-any cline-neutral"> </span>
|
|
255
314
|
<span class="cline-any cline-neutral"> </span>
|
|
256
315
|
<span class="cline-any cline-neutral"> </span>
|
|
257
|
-
<span class="cline-any cline-yes">10x</span>
|
|
258
316
|
<span class="cline-any cline-neutral"> </span>
|
|
259
317
|
<span class="cline-any cline-neutral"> </span>
|
|
260
318
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -498,12 +556,41 @@ export async function sentryOptions(
|
|
|
498
556
|
};
|
|
499
557
|
}
|
|
500
558
|
|
|
559
|
+
function getHttpStatusCode(error: unknown) {
|
|
560
|
+
if (error == null || typeof error !== 'object') {
|
|
561
|
+
return undefined;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
const {
|
|
565
|
+
status,
|
|
566
|
+
statusCode,
|
|
567
|
+
status_code: statusCodeSnake,
|
|
568
|
+
output,
|
|
569
|
+
} = error as {
|
|
570
|
+
status?: number | string;
|
|
571
|
+
statusCode?: number | string;
|
|
572
|
+
status_code?: number | string;
|
|
573
|
+
output?: { statusCode?: number | string };
|
|
574
|
+
};
|
|
575
|
+
const value = status ?? statusCode ?? statusCodeSnake ?? output?.statusCode;
|
|
576
|
+
const parsed = typeof value === 'string' ? Number.parseInt(value, 10) : value;
|
|
577
|
+
|
|
578
|
+
return typeof parsed === 'number' && Number.isFinite(parsed)
|
|
579
|
+
? parsed
|
|
580
|
+
: undefined;
|
|
581
|
+
}
|
|
582
|
+
|
|
501
583
|
export function sentryErrorHandler(
|
|
502
584
|
options: Sentry.NodeOptions = {},
|
|
503
585
|
): ErrorRequestHandler {
|
|
504
586
|
return Sentry.expressErrorHandler({
|
|
505
|
-
shouldHandleError() {
|
|
506
|
-
|
|
587
|
+
shouldHandleError(error) {
|
|
588
|
+
const status = getHttpStatusCode(error);
|
|
589
|
+
|
|
590
|
+
return (
|
|
591
|
+
process.env.NODE_ENV === 'production' &&
|
|
592
|
+
(status == null || status < 400 || status >= 500)
|
|
593
|
+
);
|
|
507
594
|
},
|
|
508
595
|
...options,
|
|
509
596
|
}) as unknown as ErrorRequestHandler;
|
|
@@ -604,7 +691,7 @@ export class SentryLoggerAdapter implements LoggerAdapter {
|
|
|
604
691
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
605
692
|
Code coverage generated by
|
|
606
693
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
607
|
-
at 2026-
|
|
694
|
+
at 2026-07-08T07:51:55.887Z
|
|
608
695
|
</div>
|
|
609
696
|
<script src="prettify.js"></script>
|
|
610
697
|
<script>
|
package/dist/index.js
CHANGED
|
@@ -53,10 +53,23 @@ export async function sentryOptions(options = {}) {
|
|
|
53
53
|
...options,
|
|
54
54
|
};
|
|
55
55
|
}
|
|
56
|
+
function getHttpStatusCode(error) {
|
|
57
|
+
if (error == null || typeof error !== 'object') {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
const { status, statusCode, status_code: statusCodeSnake, output, } = error;
|
|
61
|
+
const value = status ?? statusCode ?? statusCodeSnake ?? output?.statusCode;
|
|
62
|
+
const parsed = typeof value === 'string' ? Number.parseInt(value, 10) : value;
|
|
63
|
+
return typeof parsed === 'number' && Number.isFinite(parsed)
|
|
64
|
+
? parsed
|
|
65
|
+
: undefined;
|
|
66
|
+
}
|
|
56
67
|
export function sentryErrorHandler(options = {}) {
|
|
57
68
|
return Sentry.expressErrorHandler({
|
|
58
|
-
shouldHandleError() {
|
|
59
|
-
|
|
69
|
+
shouldHandleError(error) {
|
|
70
|
+
const status = getHttpStatusCode(error);
|
|
71
|
+
return (process.env.NODE_ENV === 'production' &&
|
|
72
|
+
(status == null || status < 400 || status >= 500));
|
|
60
73
|
},
|
|
61
74
|
...options,
|
|
62
75
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devmoods/sentry",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -24,13 +24,13 @@
|
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@devmoods/config": "0.3.0",
|
|
26
26
|
"@devmoods/observability": "0.4.0",
|
|
27
|
-
"@sentry/node": "^10.
|
|
28
|
-
"@sentry/node-native": "^10.
|
|
29
|
-
"@sentry/profiling-node": "^10.
|
|
27
|
+
"@sentry/node": "^10.64.0",
|
|
28
|
+
"@sentry/node-native": "^10.64.0",
|
|
29
|
+
"@sentry/profiling-node": "^10.64.0",
|
|
30
30
|
"express": "^4.21.2"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"express": ">=4.21.2 <5.0.0"
|
|
34
34
|
},
|
|
35
|
-
"gitHead": "
|
|
35
|
+
"gitHead": "2981e0cfae881922af5b04af07c3d3e641dece37"
|
|
36
36
|
}
|
|
@@ -59,6 +59,51 @@ test('sentryOptions', async () => {
|
|
|
59
59
|
reset();
|
|
60
60
|
});
|
|
61
61
|
|
|
62
|
+
describe('sentryErrorHandler', () => {
|
|
63
|
+
beforeEach(() => {
|
|
64
|
+
vi.unstubAllEnvs();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('ignores HTTP 40x errors in production', async () => {
|
|
68
|
+
vi.stubEnv('NODE_ENV', 'production');
|
|
69
|
+
|
|
70
|
+
const { Sentry, sentryErrorHandler } = await loadModuleWithSentryMock();
|
|
71
|
+
|
|
72
|
+
sentryErrorHandler();
|
|
73
|
+
|
|
74
|
+
const options = Sentry.expressErrorHandler.mock.calls[0]![0];
|
|
75
|
+
expect(options.shouldHandleError({ status: 400 })).toEqual(false);
|
|
76
|
+
expect(options.shouldHandleError({ statusCode: 401 })).toEqual(false);
|
|
77
|
+
expect(options.shouldHandleError({ status_code: '403' })).toEqual(false);
|
|
78
|
+
expect(options.shouldHandleError({ output: { statusCode: 429 } })).toEqual(
|
|
79
|
+
false,
|
|
80
|
+
);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test('handles server and unknown errors in production', async () => {
|
|
84
|
+
vi.stubEnv('NODE_ENV', 'production');
|
|
85
|
+
|
|
86
|
+
const { Sentry, sentryErrorHandler } = await loadModuleWithSentryMock();
|
|
87
|
+
|
|
88
|
+
sentryErrorHandler();
|
|
89
|
+
|
|
90
|
+
const options = Sentry.expressErrorHandler.mock.calls[0]![0];
|
|
91
|
+
expect(options.shouldHandleError(new Error('boom'))).toEqual(true);
|
|
92
|
+
expect(options.shouldHandleError({ status: 500 })).toEqual(true);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test('does not handle errors outside production', async () => {
|
|
96
|
+
vi.stubEnv('NODE_ENV', 'test');
|
|
97
|
+
|
|
98
|
+
const { Sentry, sentryErrorHandler } = await loadModuleWithSentryMock();
|
|
99
|
+
|
|
100
|
+
sentryErrorHandler();
|
|
101
|
+
|
|
102
|
+
const options = Sentry.expressErrorHandler.mock.calls[0]![0];
|
|
103
|
+
expect(options.shouldHandleError({ status: 500 })).toEqual(false);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
62
107
|
describe('SentryMetricsAdapter', () => {
|
|
63
108
|
beforeEach(() => {
|
|
64
109
|
vi.restoreAllMocks();
|
package/src/index.ts
CHANGED
|
@@ -77,12 +77,41 @@ export async function sentryOptions(
|
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
function getHttpStatusCode(error: unknown) {
|
|
81
|
+
if (error == null || typeof error !== 'object') {
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const {
|
|
86
|
+
status,
|
|
87
|
+
statusCode,
|
|
88
|
+
status_code: statusCodeSnake,
|
|
89
|
+
output,
|
|
90
|
+
} = error as {
|
|
91
|
+
status?: number | string;
|
|
92
|
+
statusCode?: number | string;
|
|
93
|
+
status_code?: number | string;
|
|
94
|
+
output?: { statusCode?: number | string };
|
|
95
|
+
};
|
|
96
|
+
const value = status ?? statusCode ?? statusCodeSnake ?? output?.statusCode;
|
|
97
|
+
const parsed = typeof value === 'string' ? Number.parseInt(value, 10) : value;
|
|
98
|
+
|
|
99
|
+
return typeof parsed === 'number' && Number.isFinite(parsed)
|
|
100
|
+
? parsed
|
|
101
|
+
: undefined;
|
|
102
|
+
}
|
|
103
|
+
|
|
80
104
|
export function sentryErrorHandler(
|
|
81
105
|
options: Sentry.NodeOptions = {},
|
|
82
106
|
): ErrorRequestHandler {
|
|
83
107
|
return Sentry.expressErrorHandler({
|
|
84
|
-
shouldHandleError() {
|
|
85
|
-
|
|
108
|
+
shouldHandleError(error) {
|
|
109
|
+
const status = getHttpStatusCode(error);
|
|
110
|
+
|
|
111
|
+
return (
|
|
112
|
+
process.env.NODE_ENV === 'production' &&
|
|
113
|
+
(status == null || status < 400 || status >= 500)
|
|
114
|
+
);
|
|
86
115
|
},
|
|
87
116
|
...options,
|
|
88
117
|
}) as unknown as ErrorRequestHandler;
|