|
1 | | -import { |
2 | | - flush, |
3 | | - getDefaultIsolationScope, |
4 | | - getIsolationScope, |
5 | | - GLOBAL_OBJ, |
6 | | - logger, |
7 | | - vercelWaitUntil, |
8 | | - withIsolationScope, |
9 | | -} from '@sentry/core'; |
10 | | -import * as SentryNode from '@sentry/node'; |
| 1 | +import { getDefaultIsolationScope, getIsolationScope, logger, withIsolationScope } from '@sentry/core'; |
11 | 2 | // eslint-disable-next-line import/no-extraneous-dependencies |
12 | | -import { type EventHandler, H3Error } from 'h3'; |
| 3 | +import { type EventHandler } from 'h3'; |
13 | 4 | // eslint-disable-next-line import/no-extraneous-dependencies |
14 | 5 | import { defineNitroPlugin } from 'nitropack/runtime'; |
15 | 6 | import type { NuxtRenderHTMLContext } from 'nuxt/app'; |
16 | | -import { addSentryTracingMetaTags, extractErrorContext } from '../utils'; |
| 7 | +import { addSentryTracingMetaTags, flushIfServerless } from '../utils'; |
| 8 | +import { sentryCaptureErrorHook } from '../hooks/captureErrorHook'; |
17 | 9 |
|
18 | 10 | export default defineNitroPlugin(nitroApp => { |
19 | 11 | nitroApp.h3App.handler = patchEventHandler(nitroApp.h3App.handler); |
20 | 12 |
|
21 | | - nitroApp.hooks.hook('error', async (error, errorContext) => { |
22 | | - const sentryClient = SentryNode.getClient(); |
23 | | - const sentryClientOptions = sentryClient?.getOptions(); |
24 | | - |
25 | | - if ( |
26 | | - sentryClientOptions && |
27 | | - 'enableNitroErrorHandler' in sentryClientOptions && |
28 | | - sentryClientOptions.enableNitroErrorHandler === false |
29 | | - ) { |
30 | | - return; |
31 | | - } |
32 | | - |
33 | | - // Do not handle 404 and 422 |
34 | | - if (error instanceof H3Error) { |
35 | | - // Do not report if status code is 3xx or 4xx |
36 | | - if (error.statusCode >= 300 && error.statusCode < 500) { |
37 | | - return; |
38 | | - } |
39 | | - } |
40 | | - |
41 | | - const { method, path } = { |
42 | | - method: errorContext.event?._method ? errorContext.event._method : '', |
43 | | - path: errorContext.event?._path ? errorContext.event._path : null, |
44 | | - }; |
45 | | - |
46 | | - if (path) { |
47 | | - SentryNode.getCurrentScope().setTransactionName(`${method} ${path}`); |
48 | | - } |
49 | | - |
50 | | - const structuredContext = extractErrorContext(errorContext); |
51 | | - |
52 | | - SentryNode.captureException(error, { |
53 | | - captureContext: { contexts: { nuxt: structuredContext } }, |
54 | | - mechanism: { handled: false }, |
55 | | - }); |
56 | | - |
57 | | - await flushIfServerless(); |
58 | | - }); |
| 13 | + nitroApp.hooks.hook('error', sentryCaptureErrorHook); |
59 | 14 |
|
60 | 15 | // @ts-expect-error - 'render:html' is a valid hook name in the Nuxt context |
61 | 16 | nitroApp.hooks.hook('render:html', (html: NuxtRenderHTMLContext) => { |
62 | 17 | addSentryTracingMetaTags(html.head); |
63 | 18 | }); |
64 | 19 | }); |
65 | 20 |
|
66 | | -async function flushIfServerless(): Promise<void> { |
67 | | - const isServerless = |
68 | | - !!process.env.FUNCTIONS_WORKER_RUNTIME || // Azure Functions |
69 | | - !!process.env.LAMBDA_TASK_ROOT || // AWS Lambda |
70 | | - !!process.env.VERCEL || |
71 | | - !!process.env.NETLIFY; |
72 | | - |
73 | | - // @ts-expect-error This is not typed |
74 | | - if (GLOBAL_OBJ[Symbol.for('@vercel/request-context')]) { |
75 | | - vercelWaitUntil(flushWithTimeout()); |
76 | | - } else if (isServerless) { |
77 | | - await flushWithTimeout(); |
78 | | - } |
79 | | -} |
80 | | - |
81 | | -async function flushWithTimeout(): Promise<void> { |
82 | | - const sentryClient = SentryNode.getClient(); |
83 | | - const isDebug = sentryClient ? sentryClient.getOptions().debug : false; |
84 | | - |
85 | | - try { |
86 | | - isDebug && logger.log('Flushing events...'); |
87 | | - await flush(2000); |
88 | | - isDebug && logger.log('Done flushing events'); |
89 | | - } catch (e) { |
90 | | - isDebug && logger.log('Error while flushing events:\n', e); |
91 | | - } |
92 | | -} |
93 | | - |
94 | 21 | function patchEventHandler(handler: EventHandler): EventHandler { |
95 | 22 | return new Proxy(handler, { |
96 | 23 | async apply(handlerTarget, handlerThisArg, handlerArgs: Parameters<EventHandler>) { |
|
0 commit comments