From 68a27e5cb02e07ac15269231d4b0f4e1bfd8c9c1 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Thu, 14 Nov 2024 14:50:04 +0100 Subject: [PATCH] ref: Set `normalizedRequest` instead of `request` various places The request data integration prefers this over `request`, we want to get rid of `request` in v9. Part of https://github.com/getsentry/sentry-javascript/issues/14298 --- packages/astro/src/server/middleware.ts | 2 +- packages/bun/src/integrations/bunserver.ts | 6 ++--- packages/cloudflare/src/scope-utils.ts | 2 +- .../nextjs/src/common/captureRequestError.ts | 8 ++++--- .../common/withServerActionInstrumentation.ts | 5 +++-- .../wrapGenerationFunctionWithSentry.ts | 6 ++--- .../src/common/wrapMiddlewareWithSentry.ts | 2 +- .../src/common/wrapRouteHandlerWithSentry.ts | 6 ++--- .../common/wrapServerComponentWithSentry.ts | 5 +++-- .../src/edge/wrapApiHandlerWithSentry.ts | 2 +- .../http/SentryHttpInstrumentation.ts | 18 +-------------- packages/sveltekit/src/server/handle.ts | 8 +++++-- packages/utils/src/requestdata.ts | 22 ++++++++++++++++++- 13 files changed, 52 insertions(+), 40 deletions(-) diff --git a/packages/astro/src/server/middleware.ts b/packages/astro/src/server/middleware.ts index 50c8e973adfe..cd662072cf06 100644 --- a/packages/astro/src/server/middleware.ts +++ b/packages/astro/src/server/middleware.ts @@ -111,7 +111,7 @@ async function instrumentRequest( getCurrentScope().setSDKProcessingMetadata({ // We store the request on the current scope, not isolation scope, // because we may have multiple requests nested inside each other - request: isDynamicPageRequest ? winterCGRequestToRequestData(request) : { method, url: request.url }, + normalizedRequest: isDynamicPageRequest ? winterCGRequestToRequestData(request) : { method, url: request.url }, }); if (options.trackClientIp && isDynamicPageRequest) { diff --git a/packages/bun/src/integrations/bunserver.ts b/packages/bun/src/integrations/bunserver.ts index 193ae6f286ca..7f81e3e91a9f 100644 --- a/packages/bun/src/integrations/bunserver.ts +++ b/packages/bun/src/integrations/bunserver.ts @@ -9,7 +9,7 @@ import { startSpan, withIsolationScope, } from '@sentry/core'; -import type { IntegrationFn, SpanAttributes } from '@sentry/types'; +import type { IntegrationFn, Request, SpanAttributes } from '@sentry/types'; import { getSanitizedUrlString, parseUrl } from '@sentry/utils'; const INTEGRATION_NAME = 'BunServer'; @@ -76,11 +76,11 @@ function instrumentBunServeOptions(serveOptions: Parameters[0] const url = getSanitizedUrlString(parsedUrl); isolationScope.setSDKProcessingMetadata({ - request: { + normalizedRequest: { url, method: request.method, headers: request.headers.toJSON(), - }, + } satisfies Request, }); return continueTrace( diff --git a/packages/cloudflare/src/scope-utils.ts b/packages/cloudflare/src/scope-utils.ts index 1f5bbce8f0fc..12c500b711a8 100644 --- a/packages/cloudflare/src/scope-utils.ts +++ b/packages/cloudflare/src/scope-utils.ts @@ -25,5 +25,5 @@ export function addCultureContext(scope: Scope, cf: IncomingRequestCfProperties) * Set request data on scope */ export function addRequest(scope: Scope, request: Request): void { - scope.setSDKProcessingMetadata({ request: winterCGRequestToRequestData(request) }); + scope.setSDKProcessingMetadata({ normalizedRequest: winterCGRequestToRequestData(request) }); } diff --git a/packages/nextjs/src/common/captureRequestError.ts b/packages/nextjs/src/common/captureRequestError.ts index 1556076619a0..304fc205ad0b 100644 --- a/packages/nextjs/src/common/captureRequestError.ts +++ b/packages/nextjs/src/common/captureRequestError.ts @@ -1,4 +1,6 @@ import { captureException, withScope } from '@sentry/core'; +import type { Request } from '@sentry/types'; +import { headersToDict } from '@sentry/utils'; type RequestInfo = { path: string; @@ -18,10 +20,10 @@ type ErrorContext = { export function captureRequestError(error: unknown, request: RequestInfo, errorContext: ErrorContext): void { withScope(scope => { scope.setSDKProcessingMetadata({ - request: { - headers: request.headers, + normalizedRequest: { + headers: headersToDict(request.headers), method: request.method, - }, + } satisfies Request, }); scope.setContext('nextjs', { diff --git a/packages/nextjs/src/common/withServerActionInstrumentation.ts b/packages/nextjs/src/common/withServerActionInstrumentation.ts index b13d3ebef3dd..1f68befcb47e 100644 --- a/packages/nextjs/src/common/withServerActionInstrumentation.ts +++ b/packages/nextjs/src/common/withServerActionInstrumentation.ts @@ -9,6 +9,7 @@ import { startSpan, withIsolationScope, } from '@sentry/core'; +import type { Request } from '@sentry/types'; import { logger, vercelWaitUntil } from '@sentry/utils'; import { DEBUG_BUILD } from './debug-build'; @@ -89,9 +90,9 @@ async function withServerActionInstrumentationImplementation a scope.setTransactionName(`${componentType}.${generationFunctionIdentifier} (${componentRoute})`); isolationScope.setSDKProcessingMetadata({ - request: { + normalizedRequest: { headers: headersDict, - }, + } satisfies Request, }); const activeSpan = getActiveSpan(); diff --git a/packages/nextjs/src/common/wrapMiddlewareWithSentry.ts b/packages/nextjs/src/common/wrapMiddlewareWithSentry.ts index e8b57c7d2b8b..8abcd3723eda 100644 --- a/packages/nextjs/src/common/wrapMiddlewareWithSentry.ts +++ b/packages/nextjs/src/common/wrapMiddlewareWithSentry.ts @@ -36,7 +36,7 @@ export function wrapMiddlewareWithSentry( if (req instanceof Request) { isolationScope.setSDKProcessingMetadata({ - request: winterCGRequestToRequestData(req), + normalizedRequest: winterCGRequestToRequestData(req), }); spanName = `middleware ${req.method} ${new URL(req.url).pathname}`; spanSource = 'url'; diff --git a/packages/nextjs/src/common/wrapRouteHandlerWithSentry.ts b/packages/nextjs/src/common/wrapRouteHandlerWithSentry.ts index 215bb35ce9a5..a17512b5a2d1 100644 --- a/packages/nextjs/src/common/wrapRouteHandlerWithSentry.ts +++ b/packages/nextjs/src/common/wrapRouteHandlerWithSentry.ts @@ -13,7 +13,7 @@ import { withIsolationScope, withScope, } from '@sentry/core'; - +import type { Request as SentryRequest } from '@sentry/types'; import type { RouteHandlerContext } from './types'; import { propagationContextFromHeaders, winterCGHeadersToDict } from '@sentry/utils'; @@ -64,10 +64,10 @@ export function wrapRouteHandlerWithSentry any>( ); scope.setPropagationContext(incomingPropagationContext); scope.setSDKProcessingMetadata({ - request: { + normalizedRequest: { method, headers: completeHeadersDict, - }, + } satisfies SentryRequest, }); } diff --git a/packages/nextjs/src/common/wrapServerComponentWithSentry.ts b/packages/nextjs/src/common/wrapServerComponentWithSentry.ts index c4bbde29eb53..51c5c3788db2 100644 --- a/packages/nextjs/src/common/wrapServerComponentWithSentry.ts +++ b/packages/nextjs/src/common/wrapServerComponentWithSentry.ts @@ -13,6 +13,7 @@ import { withIsolationScope, withScope, } from '@sentry/core'; +import type { Request as SentryRequest } from '@sentry/types'; import { propagationContextFromHeaders, uuid4, vercelWaitUntil, winterCGHeadersToDict } from '@sentry/utils'; import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core'; @@ -49,9 +50,9 @@ export function wrapServerComponentWithSentry any> const headersDict = context.headers ? winterCGHeadersToDict(context.headers) : undefined; isolationScope.setSDKProcessingMetadata({ - request: { + normalizedRequest: { headers: headersDict, - }, + } satisfies SentryRequest, }); return withIsolationScope(isolationScope, () => { diff --git a/packages/nextjs/src/edge/wrapApiHandlerWithSentry.ts b/packages/nextjs/src/edge/wrapApiHandlerWithSentry.ts index 5c8ce043ecb8..64bb8eceaad7 100644 --- a/packages/nextjs/src/edge/wrapApiHandlerWithSentry.ts +++ b/packages/nextjs/src/edge/wrapApiHandlerWithSentry.ts @@ -32,7 +32,7 @@ export function wrapApiHandlerWithSentry( if (req instanceof Request) { isolationScope.setSDKProcessingMetadata({ - request: winterCGRequestToRequestData(req), + normalizedRequest: winterCGRequestToRequestData(req), }); currentScope.setTransactionName(`${req.method} ${parameterizedRoute}`); } else { diff --git a/packages/node/src/integrations/http/SentryHttpInstrumentation.ts b/packages/node/src/integrations/http/SentryHttpInstrumentation.ts index 6b6fe8aaad40..921a21f6b092 100644 --- a/packages/node/src/integrations/http/SentryHttpInstrumentation.ts +++ b/packages/node/src/integrations/http/SentryHttpInstrumentation.ts @@ -10,6 +10,7 @@ import type { PolymorphicRequest, Request, SanitizedRequestData } from '@sentry/ import { getBreadcrumbLogLevelFromHttpStatusCode, getSanitizedUrlString, + headersToDict, logger, parseUrl, stripUrlQueryAndFragment, @@ -455,20 +456,3 @@ function extractQueryParams(req: IncomingMessage): string | undefined { return undefined; } } - -function headersToDict(reqHeaders: Record): Record { - const headers: Record = Object.create(null); - - try { - Object.entries(reqHeaders).forEach(([key, value]) => { - if (typeof value === 'string') { - headers[key] = value; - } - }); - } catch (e) { - DEBUG_BUILD && - logger.warn('Sentry failed extracting headers from a request object. If you see this, please file an issue.'); - } - - return headers; -} diff --git a/packages/sveltekit/src/server/handle.ts b/packages/sveltekit/src/server/handle.ts index cee8520400c1..7d8a570aa6a2 100644 --- a/packages/sveltekit/src/server/handle.ts +++ b/packages/sveltekit/src/server/handle.ts @@ -131,7 +131,9 @@ export function sentryHandle(handlerOptions?: SentryHandleOptions): Handle { return withIsolationScope(isolationScope => { // We only call continueTrace in the initial top level request to avoid // creating a new root span for the sub request. - isolationScope.setSDKProcessingMetadata({ request: winterCGRequestToRequestData(input.event.request.clone()) }); + isolationScope.setSDKProcessingMetadata({ + normalizedRequest: winterCGRequestToRequestData(input.event.request.clone()), + }); return continueTrace(getTracePropagationData(input.event), () => instrumentHandle(input, options)); }); }; @@ -167,7 +169,9 @@ async function instrumentHandle( name: routeName, }, async (span?: Span) => { - getCurrentScope().setSDKProcessingMetadata({ request: winterCGRequestToRequestData(event.request.clone()) }); + getCurrentScope().setSDKProcessingMetadata({ + normalizedRequest: winterCGRequestToRequestData(event.request.clone()), + }); const res = await resolve(event, { transformPageChunk: addSentryCodeToPage(options), }); diff --git a/packages/utils/src/requestdata.ts b/packages/utils/src/requestdata.ts index edffc6f67da7..3b0915e9d959 100644 --- a/packages/utils/src/requestdata.ts +++ b/packages/utils/src/requestdata.ts @@ -434,10 +434,30 @@ export function winterCGHeadersToDict(winterCGHeaders: WebFetchHeaders): Record< return headers; } +/** + * Convert common request headers to a simple dictionary. + */ +export function headersToDict(reqHeaders: Record): Record { + const headers: Record = Object.create(null); + + try { + Object.entries(reqHeaders).forEach(([key, value]) => { + if (typeof value === 'string') { + headers[key] = value; + } + }); + } catch (e) { + DEBUG_BUILD && + logger.warn('Sentry failed extracting headers from a request object. If you see this, please file an issue.'); + } + + return headers; +} + /** * Converts a `Request` object that implements the `Web Fetch API` (https://developer.mozilla.org/en-US/docs/Web/API/Headers) into the format that the `RequestData` integration understands. */ -export function winterCGRequestToRequestData(req: WebFetchRequest): PolymorphicRequest { +export function winterCGRequestToRequestData(req: WebFetchRequest): Request { const headers = winterCGHeadersToDict(req.headers); return { method: req.method,