From 624ee8169b0aca5429a64aa40d9015c12599602c Mon Sep 17 00:00:00 2001 From: s1gr1d Date: Mon, 7 Oct 2024 16:32:31 +0200 Subject: [PATCH 1/3] feat(nuxt/nitro): Flush with `waitUntil` after response --- .../nuxt/src/runtime/plugins/sentry.server.ts | 8 ++++- packages/nuxt/src/runtime/utils.ts | 32 +++++++++++++++++-- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/packages/nuxt/src/runtime/plugins/sentry.server.ts b/packages/nuxt/src/runtime/plugins/sentry.server.ts index 1159a6d427ff..2eb51ce4cb0e 100644 --- a/packages/nuxt/src/runtime/plugins/sentry.server.ts +++ b/packages/nuxt/src/runtime/plugins/sentry.server.ts @@ -2,7 +2,7 @@ import * as Sentry from '@sentry/node'; import { H3Error } from 'h3'; import { defineNitroPlugin } from 'nitropack/runtime'; import type { NuxtRenderHTMLContext } from 'nuxt/app'; -import { addSentryTracingMetaTags, extractErrorContext } from '../utils'; +import { addSentryTracingMetaTags, extractErrorContext, vercelWaitUntilAndFlush } from '../utils'; export default defineNitroPlugin(nitroApp => { nitroApp.hooks.hook('error', (error, errorContext) => { @@ -29,10 +29,16 @@ export default defineNitroPlugin(nitroApp => { captureContext: { contexts: { nuxt: structuredContext } }, mechanism: { handled: false }, }); + + vercelWaitUntilAndFlush(); }); // @ts-expect-error - 'render:html' is a valid hook name in the Nuxt context nitroApp.hooks.hook('render:html', (html: NuxtRenderHTMLContext) => { addSentryTracingMetaTags(html.head); }); + + nitroApp.hooks.hook('request', () => { + vercelWaitUntilAndFlush(); + }); }); diff --git a/packages/nuxt/src/runtime/utils.ts b/packages/nuxt/src/runtime/utils.ts index 7b56a258f708..6dfab05fd1ff 100644 --- a/packages/nuxt/src/runtime/utils.ts +++ b/packages/nuxt/src/runtime/utils.ts @@ -1,6 +1,6 @@ -import { captureException, getClient, getTraceMetaTags } from '@sentry/core'; +import { captureException, flush, getClient, getTraceMetaTags } from '@sentry/core'; import type { ClientOptions, Context } from '@sentry/types'; -import { dropUndefinedKeys } from '@sentry/utils'; +import { dropUndefinedKeys, logger, vercelWaitUntil } from '@sentry/utils'; import type { VueOptions } from '@sentry/vue/src/types'; import type { CapturedErrorContext } from 'nitropack'; import type { NuxtRenderHTMLContext } from 'nuxt/app'; @@ -80,3 +80,31 @@ export function reportNuxtError(options: { }); }); } + +/** + * Flushes pending Sentry events with a 2 seconds timeout and in a way that cannot create unhandled promise rejections. + * + */ +export async function flushSafelyWithTimeout(isDebug: boolean): Promise { + try { + isDebug && logger.log('Flushing events...'); + await flush(2000); + isDebug && logger.log('Done flushing events'); + } catch (e) { + isDebug && logger.log('Error while flushing events:\n', e); + } +} + +/** + * Utility function for the Nuxt module runtime function as we always have to get the client instance to get + * the `debug` option (we cannot access BUILD_DEBUG in the module runtime). + * + * This function should be called when Nitro ends a request (so Vercel can wait). + */ +export function vercelWaitUntilAndFlush(): void { + const sentryClient = getClient(); + + if (sentryClient) { + vercelWaitUntil(flushSafelyWithTimeout(sentryClient.getOptions().debug || false)); + } +} From 09f91367592c52228d86f6d7f9cb271e98b9f71f Mon Sep 17 00:00:00 2001 From: s1gr1d Date: Mon, 7 Oct 2024 16:37:14 +0200 Subject: [PATCH 2/3] modify comment --- packages/nuxt/src/runtime/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nuxt/src/runtime/utils.ts b/packages/nuxt/src/runtime/utils.ts index 6dfab05fd1ff..7b52f7c1951f 100644 --- a/packages/nuxt/src/runtime/utils.ts +++ b/packages/nuxt/src/runtime/utils.ts @@ -96,7 +96,7 @@ export async function flushSafelyWithTimeout(isDebug: boolean): Promise { } /** - * Utility function for the Nuxt module runtime function as we always have to get the client instance to get + * Utility function for the Nuxt module runtime as we always have to get the client instance to get * the `debug` option (we cannot access BUILD_DEBUG in the module runtime). * * This function should be called when Nitro ends a request (so Vercel can wait). From b5290aad3dd464c90acfb6d38b201d733aa2b60f Mon Sep 17 00:00:00 2001 From: s1gr1d Date: Tue, 15 Oct 2024 15:33:52 +0200 Subject: [PATCH 3/3] fix hook name --- packages/nuxt/src/runtime/plugins/sentry.server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nuxt/src/runtime/plugins/sentry.server.ts b/packages/nuxt/src/runtime/plugins/sentry.server.ts index 2eb51ce4cb0e..d8e46ab96d51 100644 --- a/packages/nuxt/src/runtime/plugins/sentry.server.ts +++ b/packages/nuxt/src/runtime/plugins/sentry.server.ts @@ -38,7 +38,7 @@ export default defineNitroPlugin(nitroApp => { addSentryTracingMetaTags(html.head); }); - nitroApp.hooks.hook('request', () => { + nitroApp.hooks.hook('afterResponse', () => { vercelWaitUntilAndFlush(); }); });