From f6872addba0c62d798446bed208881440532c5dd Mon Sep 17 00:00:00 2001 From: s1gr1d Date: Tue, 15 Oct 2024 15:15:37 +0200 Subject: [PATCH 1/3] feat(nuxt): Add Http `responseHook` with `waitUntil` --- packages/nuxt/src/server/sdk.ts | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/packages/nuxt/src/server/sdk.ts b/packages/nuxt/src/server/sdk.ts index a6599b4ac088..4924bb10699c 100644 --- a/packages/nuxt/src/server/sdk.ts +++ b/packages/nuxt/src/server/sdk.ts @@ -1,7 +1,7 @@ -import { applySdkMetadata, getGlobalScope } from '@sentry/core'; -import { init as initNode } from '@sentry/node'; +import { applySdkMetadata, flush, getGlobalScope } from '@sentry/core'; +import { httpIntegration, init as initNode } from '@sentry/node'; import type { Client, EventProcessor } from '@sentry/types'; -import { logger } from '@sentry/utils'; +import { logger, vercelWaitUntil } from '@sentry/utils'; import { DEBUG_BUILD } from '../common/debug-build'; import type { SentryNuxtServerOptions } from '../common/types'; @@ -14,6 +14,17 @@ export function init(options: SentryNuxtServerOptions): Client | undefined { const sentryOptions = { ...options, registerEsmLoaderHooks: mergeRegisterEsmLoaderHooks(options), + integrations: [ + httpIntegration({ + instrumentation: { + responseHook: () => { + // Makes it possible to end the tracing span before closing the Vercel lambda (https://vercel.com/docs/functions/functions-api-reference#waituntil) + vercelWaitUntil(flushSafelyWithTimeout()); + }, + }, + }), + ...(Array.isArray(options.integrations) ? options.integrations : []), + ], }; applySdkMetadata(sentryOptions, 'nuxt', ['nuxt', 'node']); @@ -64,3 +75,16 @@ export function mergeRegisterEsmLoaderHooks( } return options.registerEsmLoaderHooks ?? { exclude: [/vue/] }; } + +/** + * Flushes pending Sentry events with a 2-second timeout and in a way that cannot create unhandled promise rejections. + */ +export async function flushSafelyWithTimeout(): Promise { + try { + DEBUG_BUILD && logger.log('Flushing events...'); + await flush(2000); + DEBUG_BUILD && logger.log('Done flushing events'); + } catch (e) { + DEBUG_BUILD && logger.log('Error while flushing events:\n', e); + } +} From c628d99a6cb6a44429077236c11503a03838e2cd Mon Sep 17 00:00:00 2001 From: s1gr1d Date: Thu, 17 Oct 2024 14:48:34 +0200 Subject: [PATCH 2/3] add httpIntegration with hook to defaultIntegrations --- packages/nuxt/src/server/sdk.ts | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/packages/nuxt/src/server/sdk.ts b/packages/nuxt/src/server/sdk.ts index 4924bb10699c..1eb75346f29e 100644 --- a/packages/nuxt/src/server/sdk.ts +++ b/packages/nuxt/src/server/sdk.ts @@ -1,6 +1,7 @@ import { applySdkMetadata, flush, getGlobalScope } from '@sentry/core'; -import { httpIntegration, init as initNode } from '@sentry/node'; -import type { Client, EventProcessor } from '@sentry/types'; +import { type NodeOptions, httpIntegration, init as initNode } from '@sentry/node'; +import { getDefaultIntegrations as getDefaultNodeIntegrations } from '@sentry/node/build/types/sdk'; +import type { Client, EventProcessor, Integration } from '@sentry/types'; import { logger, vercelWaitUntil } from '@sentry/utils'; import { DEBUG_BUILD } from '../common/debug-build'; import type { SentryNuxtServerOptions } from '../common/types'; @@ -14,17 +15,7 @@ export function init(options: SentryNuxtServerOptions): Client | undefined { const sentryOptions = { ...options, registerEsmLoaderHooks: mergeRegisterEsmLoaderHooks(options), - integrations: [ - httpIntegration({ - instrumentation: { - responseHook: () => { - // Makes it possible to end the tracing span before closing the Vercel lambda (https://vercel.com/docs/functions/functions-api-reference#waituntil) - vercelWaitUntil(flushSafelyWithTimeout()); - }, - }, - }), - ...(Array.isArray(options.integrations) ? options.integrations : []), - ], + defaultIntegrations: getNuxtDefaultIntegrations(options), }; applySdkMetadata(sentryOptions, 'nuxt', ['nuxt', 'node']); @@ -57,6 +48,21 @@ export function init(options: SentryNuxtServerOptions): Client | undefined { return client; } +function getNuxtDefaultIntegrations(options: NodeOptions): Integration[] { + return [ + ...getDefaultNodeIntegrations(options).filter(integration => integration.name !== 'Http'), + // The httpIntegration is added as defaultIntegration, so users can still overwrite it + httpIntegration({ + instrumentation: { + responseHook: () => { + // Makes it possible to end the tracing span before closing the Vercel lambda (https://vercel.com/docs/functions/functions-api-reference#waituntil) + vercelWaitUntil(flushSafelyWithTimeout()); + }, + }, + }), + ]; +} + /** * Adds /vue/ to the registerEsmLoaderHooks options and merges it with the old values in the array if one is defined. * If the registerEsmLoaderHooks option is already a boolean, nothing is changed. From 6976485fe264e9b890a0849fe407982297555b22 Mon Sep 17 00:00:00 2001 From: s1gr1d Date: Thu, 17 Oct 2024 16:11:17 +0200 Subject: [PATCH 3/3] fix test --- packages/nuxt/src/server/sdk.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/nuxt/src/server/sdk.ts b/packages/nuxt/src/server/sdk.ts index 1eb75346f29e..59832bbb2a39 100644 --- a/packages/nuxt/src/server/sdk.ts +++ b/packages/nuxt/src/server/sdk.ts @@ -1,6 +1,10 @@ import { applySdkMetadata, flush, getGlobalScope } from '@sentry/core'; -import { type NodeOptions, httpIntegration, init as initNode } from '@sentry/node'; -import { getDefaultIntegrations as getDefaultNodeIntegrations } from '@sentry/node/build/types/sdk'; +import { + type NodeOptions, + getDefaultIntegrations as getDefaultNodeIntegrations, + httpIntegration, + init as initNode, +} from '@sentry/node'; import type { Client, EventProcessor, Integration } from '@sentry/types'; import { logger, vercelWaitUntil } from '@sentry/utils'; import { DEBUG_BUILD } from '../common/debug-build';