Skip to content

Commit de110de

Browse files
committed
ref: Refactor remaining usage of request to normalizedRequest
This includes exporting `httpRequestToRequestEventData` from `@sentry/node`, which we can reuse in a few places.
1 parent 7e78d67 commit de110de

File tree

11 files changed

+73
-335
lines changed

11 files changed

+73
-335
lines changed

packages/google-cloud-serverless/src/gcpfunction/http.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
import {
2+
handleCallbackErrors,
3+
isString,
4+
logger,
25
SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
36
SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
4-
handleCallbackErrors,
57
setHttpStatus,
8+
stripUrlQueryAndFragment,
69
} from '@sentry/core';
7-
import { isString, logger, stripUrlQueryAndFragment } from '@sentry/core';
8-
import { captureException, continueTrace, flush, getCurrentScope, startSpanManual } from '@sentry/node';
9-
10+
import {
11+
captureException,
12+
continueTrace,
13+
flush,
14+
getCurrentScope,
15+
httpRequestToRequestEventData,
16+
startSpanManual,
17+
} from '@sentry/node';
1018
import { DEBUG_BUILD } from '../debug-build';
1119
import { domainify, markEventUnhandled, proxyFunction } from '../utils';
1220
import type { HttpFunction, WrapperOptions } from './general';
@@ -44,6 +52,9 @@ function _wrapHttpFunction(fn: HttpFunction, options: Partial<WrapperOptions>):
4452
const baggage = req.headers?.baggage;
4553

4654
return continueTrace({ sentryTrace, baggage }, () => {
55+
const normalizedRequest = httpRequestToRequestEventData(req);
56+
getCurrentScope().setSDKProcessingMetadata({ normalizedRequest });
57+
4758
return startSpanManual(
4859
{
4960
name: `${reqMethod} ${reqUrl}`,
@@ -54,10 +65,6 @@ function _wrapHttpFunction(fn: HttpFunction, options: Partial<WrapperOptions>):
5465
},
5566
},
5667
span => {
57-
getCurrentScope().setSDKProcessingMetadata({
58-
request: req,
59-
});
60-
6168
// eslint-disable-next-line @typescript-eslint/unbound-method
6269
const _end = res.end;
6370
// eslint-disable-next-line @typescript-eslint/no-explicit-any

packages/nextjs/src/common/pages-router-instrumentation/_error.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { captureException, withScope } from '@sentry/core';
22
import { vercelWaitUntil } from '@sentry/core';
3+
import { httpRequestToRequestEventData } from '@sentry/node';
34
import type { NextPageContext } from 'next';
45
import { flushSafelyWithTimeout } from '../utils/responseEnd';
56

@@ -38,7 +39,8 @@ export async function captureUnderscoreErrorException(contextOrProps: ContextOrP
3839

3940
withScope(scope => {
4041
if (req) {
41-
scope.setSDKProcessingMetadata({ request: req });
42+
const normalizedRequest = httpRequestToRequestEventData(req);
43+
scope.setSDKProcessingMetadata({ normalizedRequest });
4244
}
4345

4446
// If third-party libraries (or users themselves) throw something falsy, we want to capture it as a message (which

packages/nextjs/src/common/pages-router-instrumentation/wrapApiHandlerWithSentry.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
import { isString, logger, objectify } from '@sentry/core';
1111

1212
import { vercelWaitUntil } from '@sentry/core';
13+
import { httpRequestToRequestEventData } from '@sentry/node';
1314
import type { NextApiRequest } from 'next';
1415
import type { AugmentedNextApiResponse, NextApiHandler } from '../types';
1516
import { flushSafelyWithTimeout } from '../utils/responseEnd';
@@ -65,8 +66,9 @@ export function wrapApiHandlerWithSentry(apiHandler: NextApiHandler, parameteriz
6566
},
6667
() => {
6768
const reqMethod = `${(req.method || 'GET').toUpperCase()} `;
69+
const normalizedRequest = httpRequestToRequestEventData(req);
6870

69-
isolationScope.setSDKProcessingMetadata({ request: req });
71+
isolationScope.setSDKProcessingMetadata({ normalizedRequest });
7072
isolationScope.setTransactionName(`${reqMethod}${parameterizedRoute}`);
7173

7274
return startSpanManual(

packages/nextjs/src/common/utils/wrapperUtils.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import type { IncomingMessage, ServerResponse } from 'http';
21
import {
32
captureException,
43
getActiveSpan,
@@ -7,6 +6,8 @@ import {
76
getRootSpan,
87
getTraceData,
98
} from '@sentry/core';
9+
import { httpRequestToRequestEventData } from '@sentry/node';
10+
import type { IncomingMessage, ServerResponse } from 'http';
1011
import { TRANSACTION_ATTR_SENTRY_ROUTE_BACKFILL } from '../span-attributes-with-logic-attached';
1112

1213
/**
@@ -61,10 +62,9 @@ export function withTracedServerSideDataFetcher<F extends (...args: any[]) => Pr
6162
this: unknown,
6263
...args: Parameters<F>
6364
): Promise<{ data: ReturnType<F>; sentryTrace?: string; baggage?: string }> {
65+
const normalizedRequest = httpRequestToRequestEventData(req);
6466
getCurrentScope().setTransactionName(`${options.dataFetchingMethodName} (${options.dataFetcherRouteName})`);
65-
getIsolationScope().setSDKProcessingMetadata({
66-
request: req,
67-
});
67+
getIsolationScope().setSDKProcessingMetadata({ normalizedRequest });
6868

6969
const span = getActiveSpan();
7070

packages/nextjs/src/common/wrapMiddlewareWithSentry.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ import {
88
handleCallbackErrors,
99
setCapturedScopesOnSpan,
1010
startSpan,
11+
vercelWaitUntil,
12+
winterCGRequestToRequestData,
1113
withIsolationScope,
1214
} from '@sentry/core';
13-
import { vercelWaitUntil, winterCGRequestToRequestData } from '@sentry/core';
1415
import type { TransactionSource } from '@sentry/types';
1516
import type { EdgeRouteHandler } from '../edge/types';
1617
import { flushSafelyWithTimeout } from './utils/responseEnd';

packages/node/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export { httpIntegration } from './integrations/http';
2+
export { httpRequestToRequestEventData } from './integrations/http/SentryHttpInstrumentation';
23
export { nativeNodeFetchIntegration } from './integrations/node-fetch';
34
export { fsIntegration } from './integrations/fs';
45

packages/node/src/integrations/http/SentryHttpInstrumentation.ts

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -131,26 +131,9 @@ export class SentryHttpInstrumentation extends InstrumentationBase<SentryHttpIns
131131

132132
instrumentation._diag.debug('http instrumentation for incoming request');
133133

134-
const request = args[0] as http.IncomingMessage;
135-
136134
const isolationScope = getIsolationScope().clone();
137-
138-
const headers = request.headers;
139-
const host = headers.host || '<no host>';
140-
const protocol = request.socket && (request.socket as { encrypted?: boolean }).encrypted ? 'https' : 'http';
141-
const originalUrl = request.url || '';
142-
const absoluteUrl = originalUrl.startsWith(protocol) ? originalUrl : `${protocol}://${host}${originalUrl}`;
143-
144-
// This is non-standard, but may be set on e.g. Next.js or Express requests
145-
const cookies = (request as PolymorphicRequest).cookies;
146-
147-
const normalizedRequest: RequestEventData = {
148-
url: absoluteUrl,
149-
method: request.method,
150-
query_string: extractQueryParamsFromUrl(request.url || ''),
151-
headers: headersToDict(request.headers),
152-
cookies,
153-
};
135+
const request = args[0] as http.IncomingMessage;
136+
const normalizedRequest = httpRequestToRequestEventData(request);
154137

155138
patchRequestToCaptureBody(request, isolationScope);
156139

@@ -445,3 +428,27 @@ function patchRequestToCaptureBody(req: IncomingMessage, isolationScope: Scope):
445428
// ignore errors if we can't patch stuff
446429
}
447430
}
431+
432+
/**
433+
* Convert a HTTP request object to RequestEventData to be passed as normalizedRequest.
434+
*/
435+
export function httpRequestToRequestEventData(request: IncomingMessage): RequestEventData {
436+
const headers = request.headers;
437+
const host = headers.host || '<no host>';
438+
const protocol = request.socket && (request.socket as { encrypted?: boolean }).encrypted ? 'https' : 'http';
439+
const originalUrl = request.url || '';
440+
const absoluteUrl = originalUrl.startsWith(protocol) ? originalUrl : `${protocol}://${host}${originalUrl}`;
441+
442+
// This is non-standard, but may be set on e.g. Next.js or Express requests
443+
const cookies = (request as PolymorphicRequest).cookies;
444+
445+
const normalizedRequest: RequestEventData = {
446+
url: absoluteUrl,
447+
method: request.method,
448+
query_string: extractQueryParamsFromUrl(request.url || ''),
449+
headers: headersToDict(request.headers),
450+
cookies,
451+
};
452+
453+
return normalizedRequest;
454+
}

packages/remix/src/utils/errors.ts

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
import type { AppData, DataFunctionArgs, EntryContext, HandleDocumentRequestFunction } from '@remix-run/node';
2-
import { captureException, getClient, handleCallbackErrors } from '@sentry/core';
3-
import { addExceptionMechanism, isPrimitive, logger, objectify } from '@sentry/core';
4-
import type { Span } from '@sentry/types';
2+
import {
3+
addExceptionMechanism,
4+
captureException,
5+
getClient,
6+
handleCallbackErrors,
7+
isPrimitive,
8+
logger,
9+
objectify,
10+
winterCGRequestToRequestData,
11+
} from '@sentry/core';
12+
import type { RequestEventData, Span } from '@sentry/types';
513
import { DEBUG_BUILD } from './debug-build';
614
import type { RemixOptions } from './remixOptions';
715
import { storeFormDataKeys } from './utils';
816
import { extractData, isResponse, isRouteErrorResponse } from './vendor/response';
917
import type { DataFunction, RemixRequest } from './vendor/types';
10-
import { normalizeRemixRequest } from './web-fetch';
1118

1219
/**
1320
* Captures an exception happened in the Remix server.
@@ -41,24 +48,18 @@ export async function captureRemixServerException(
4148
return;
4249
}
4350

44-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
45-
let normalizedRequest: Record<string, unknown> = request as unknown as any;
51+
let normalizedRequest: RequestEventData = {};
4652

4753
try {
48-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
49-
normalizedRequest = normalizeRemixRequest(request as unknown as any);
54+
normalizedRequest = winterCGRequestToRequestData(request);
5055
} catch (e) {
5156
DEBUG_BUILD && logger.warn('Failed to normalize Remix request');
5257
}
5358

5459
const objectifiedErr = objectify(err);
5560

5661
captureException(isResponse(objectifiedErr) ? await extractResponseError(objectifiedErr) : objectifiedErr, scope => {
57-
scope.setSDKProcessingMetadata({
58-
request: {
59-
...normalizedRequest,
60-
},
61-
});
62+
scope.setSDKProcessingMetadata({ normalizedRequest });
6263

6364
scope.addEventProcessor(event => {
6465
addExceptionMechanism(event, {

packages/remix/src/utils/instrumentServer.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ import {
1111
spanToJSON,
1212
spanToTraceHeader,
1313
startSpan,
14+
winterCGRequestToRequestData,
1415
withIsolationScope,
1516
} from '@sentry/core';
1617
import { dynamicSamplingContextToSentryBaggageHeader, fill, isNodeEnv, loadModule, logger } from '@sentry/core';
1718
import { continueTrace, getDynamicSamplingContextFromSpan } from '@sentry/opentelemetry';
18-
import type { TransactionSource, WrappedFunction } from '@sentry/types';
19+
import type { RequestEventData, TransactionSource, WrappedFunction } from '@sentry/types';
1920
import type { Span } from '@sentry/types';
2021

2122
import { DEBUG_BUILD } from './debug-build';
@@ -39,7 +40,6 @@ import type {
3940
ServerRoute,
4041
ServerRouteManifest,
4142
} from './vendor/types';
42-
import { normalizeRemixRequest } from './web-fetch';
4343

4444
let FUTURE_FLAGS: FutureConfig | undefined;
4545

@@ -296,10 +296,10 @@ function wrapRequestHandler(
296296
return withIsolationScope(async isolationScope => {
297297
const options = getClient()?.getOptions();
298298

299-
let normalizedRequest: Record<string, unknown> = request;
299+
let normalizedRequest: RequestEventData = {};
300300

301301
try {
302-
normalizedRequest = normalizeRemixRequest(request);
302+
normalizedRequest = winterCGRequestToRequestData(request);
303303
} catch (e) {
304304
DEBUG_BUILD && logger.warn('Failed to normalize Remix request');
305305
}
@@ -311,11 +311,7 @@ function wrapRequestHandler(
311311
isolationScope.setTransactionName(name);
312312
}
313313

314-
isolationScope.setSDKProcessingMetadata({
315-
request: {
316-
...normalizedRequest,
317-
},
318-
});
314+
isolationScope.setSDKProcessingMetadata({ normalizedRequest });
319315

320316
if (!options || !hasTracingEnabled(options)) {
321317
return origRequestHandler.call(this, request, loadContext);

0 commit comments

Comments
 (0)