From 2f6278384516b7ea8c13d3a9e82d1c073190b006 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Wed, 3 Apr 2024 08:52:21 +0000 Subject: [PATCH 1/4] feat(v7): Deprecate and relocate `trpcMiddleware` The `trpcMiddleware` export will move from `Handlers` to a top level export in v8. This is more or less backporting https://github.com/getsentry/sentry-javascript/pull/11374 to v7. --- packages/astro/src/index.server.ts | 1 + packages/node/src/handlers.ts | 84 +++++--------------------- packages/node/src/index.ts | 2 + packages/node/src/trpc.ts | 77 +++++++++++++++++++++++ packages/remix/src/index.server.ts | 1 + packages/serverless/src/index.ts | 1 + packages/sveltekit/src/server/index.ts | 1 + 7 files changed, 97 insertions(+), 70 deletions(-) create mode 100644 packages/node/src/trpc.ts diff --git a/packages/astro/src/index.server.ts b/packages/astro/src/index.server.ts index ac534318ce24..5d57783d8b74 100644 --- a/packages/astro/src/index.server.ts +++ b/packages/astro/src/index.server.ts @@ -83,6 +83,7 @@ export { inboundFiltersIntegration, linkedErrorsIntegration, Handlers, + trpcMiddleware, setMeasurement, getActiveSpan, startSpan, diff --git a/packages/node/src/handlers.ts b/packages/node/src/handlers.ts index 333c9022bf9b..6f02864f4ef5 100644 --- a/packages/node/src/handlers.ts +++ b/packages/node/src/handlers.ts @@ -22,9 +22,7 @@ import { extractPathForTransaction, extractRequestData, isString, - isThenable, logger, - normalize, } from '@sentry/utils'; import type { NodeClient } from './client'; @@ -32,6 +30,7 @@ import { DEBUG_BUILD } from './debug-build'; // TODO (v8 / XXX) Remove this import import type { ParseRequestOptions } from './requestDataDeprecated'; import { isAutoSessionTrackingEnabled } from './sdk'; +import { trpcMiddleware as newTrpcMiddleware } from './trpc'; /** * Express-compatible tracing handler. @@ -316,80 +315,25 @@ export function errorHandler(options?: { }; } -interface SentryTrpcMiddlewareOptions { - /** Whether to include procedure inputs in reported events. Defaults to `false`. */ - attachRpcInput?: boolean; -} - -interface TrpcMiddlewareArguments { - path: string; - type: string; - next: () => T; - rawInput: unknown; -} - /** * Sentry tRPC middleware that names the handling transaction after the called procedure. * * Use the Sentry tRPC middleware in combination with the Sentry server integration, * e.g. Express Request Handlers or Next.js SDK. + * + * @deprecated Please use the top level export instead: + * ``` + * // OLD + * import * as Sentry from '@sentry/node'; + * Sentry.Handlers.trpcMiddleware(); + * + * // NEW + * import * as Sentry from '@sentry/node'; + * Sentry.trpcMiddleware(); + * ``` */ -export function trpcMiddleware(options: SentryTrpcMiddlewareOptions = {}) { - return function ({ path, type, next, rawInput }: TrpcMiddlewareArguments): T { - const clientOptions = getClient()?.getOptions(); - // eslint-disable-next-line deprecation/deprecation - const sentryTransaction = getCurrentScope().getTransaction(); - - if (sentryTransaction) { - sentryTransaction.updateName(`trpc/${path}`); - sentryTransaction.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, 'route'); - sentryTransaction.op = 'rpc.server'; - - const trpcContext: Record = { - procedure_type: type, - }; - - if (options.attachRpcInput !== undefined ? options.attachRpcInput : clientOptions?.sendDefaultPii) { - trpcContext.input = normalize(rawInput); - } - - // TODO: Can we rewrite this to an attribute? Or set this on the scope? - // eslint-disable-next-line deprecation/deprecation - sentryTransaction.setContext('trpc', trpcContext); - } - - function captureIfError(nextResult: { ok: false; error?: Error } | { ok: true }): void { - if (!nextResult.ok) { - captureException(nextResult.error, { mechanism: { handled: false, data: { function: 'trpcMiddleware' } } }); - } - } - - let maybePromiseResult; - try { - maybePromiseResult = next(); - } catch (e) { - captureException(e, { mechanism: { handled: false, data: { function: 'trpcMiddleware' } } }); - throw e; - } - - if (isThenable(maybePromiseResult)) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - Promise.resolve(maybePromiseResult).then( - nextResult => { - captureIfError(nextResult as any); - }, - e => { - captureException(e, { mechanism: { handled: false, data: { function: 'trpcMiddleware' } } }); - }, - ); - } else { - captureIfError(maybePromiseResult as any); - } - - // We return the original promise just to be safe. - return maybePromiseResult; - }; -} +// eslint-disable-next-line deprecation/deprecation +export const trpcMiddleware = newTrpcMiddleware; // TODO (v8 / #5257): Remove this // eslint-disable-next-line deprecation/deprecation diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index 8fb5ec6968b4..9f10251aa9e3 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -167,6 +167,8 @@ export type { AnrIntegrationOptions } from './integrations/anr/common'; export { Handlers }; +export { trpcMiddleware } from './trpc'; + export { hapiErrorPlugin } from './integrations/hapi'; import { instrumentCron } from './cron/cron'; diff --git a/packages/node/src/trpc.ts b/packages/node/src/trpc.ts new file mode 100644 index 000000000000..8fec3e487e0b --- /dev/null +++ b/packages/node/src/trpc.ts @@ -0,0 +1,77 @@ +import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, captureException, getClient, getCurrentScope } from '@sentry/core'; +import { isThenable, normalize } from '@sentry/utils'; + +interface SentryTrpcMiddlewareOptions { + /** Whether to include procedure inputs in reported events. Defaults to `false`. */ + attachRpcInput?: boolean; +} + +interface TrpcMiddlewareArguments { + path: string; + type: string; + next: () => T; + rawInput: unknown; +} + +/** + * Sentry tRPC middleware that names the handling transaction after the called procedure. + * + * Use the Sentry tRPC middleware in combination with the Sentry server integration, + * e.g. Express Request Handlers or Next.js SDK. + */ +export function trpcMiddleware(options: SentryTrpcMiddlewareOptions = {}) { + return function ({ path, type, next, rawInput }: TrpcMiddlewareArguments): T { + const clientOptions = getClient()?.getOptions(); + // eslint-disable-next-line deprecation/deprecation + const sentryTransaction = getCurrentScope().getTransaction(); + + if (sentryTransaction) { + sentryTransaction.updateName(`trpc/${path}`); + sentryTransaction.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, 'route'); + sentryTransaction.op = 'rpc.server'; + + const trpcContext: Record = { + procedure_type: type, + }; + + if (options.attachRpcInput !== undefined ? options.attachRpcInput : clientOptions?.sendDefaultPii) { + trpcContext.input = normalize(rawInput); + } + + // TODO: Can we rewrite this to an attribute? Or set this on the scope? + // eslint-disable-next-line deprecation/deprecation + sentryTransaction.setContext('trpc', trpcContext); + } + + function captureIfError(nextResult: { ok: false; error?: Error } | { ok: true }): void { + if (!nextResult.ok) { + captureException(nextResult.error, { mechanism: { handled: false, data: { function: 'trpcMiddleware' } } }); + } + } + + let maybePromiseResult; + try { + maybePromiseResult = next(); + } catch (e) { + captureException(e, { mechanism: { handled: false, data: { function: 'trpcMiddleware' } } }); + throw e; + } + + if (isThenable(maybePromiseResult)) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + Promise.resolve(maybePromiseResult).then( + nextResult => { + captureIfError(nextResult as any); + }, + e => { + captureException(e, { mechanism: { handled: false, data: { function: 'trpcMiddleware' } } }); + }, + ); + } else { + captureIfError(maybePromiseResult as any); + } + + // We return the original promise just to be safe. + return maybePromiseResult; + }; +} diff --git a/packages/remix/src/index.server.ts b/packages/remix/src/index.server.ts index fa1c20ecc22c..e5386471f3d9 100644 --- a/packages/remix/src/index.server.ts +++ b/packages/remix/src/index.server.ts @@ -87,6 +87,7 @@ export { inboundFiltersIntegration, linkedErrorsIntegration, Handlers, + trpcMiddleware, setMeasurement, getActiveSpan, startSpan, diff --git a/packages/serverless/src/index.ts b/packages/serverless/src/index.ts index d2a136c5ab34..ccd39fb159bd 100644 --- a/packages/serverless/src/index.ts +++ b/packages/serverless/src/index.ts @@ -73,6 +73,7 @@ export { // eslint-disable-next-line deprecation/deprecation deepReadDirSync, Handlers, + trpcMiddleware, // eslint-disable-next-line deprecation/deprecation Integrations, setMeasurement, diff --git a/packages/sveltekit/src/server/index.ts b/packages/sveltekit/src/server/index.ts index 1ee7e75b9136..167c4907099a 100644 --- a/packages/sveltekit/src/server/index.ts +++ b/packages/sveltekit/src/server/index.ts @@ -81,6 +81,7 @@ export { inboundFiltersIntegration, linkedErrorsIntegration, Handlers, + trpcMiddleware, setMeasurement, getActiveSpan, startSpan, From 8ad0f902e5093e7307303d48f63cee77149309e6 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Wed, 3 Apr 2024 09:38:10 +0000 Subject: [PATCH 2/4] Add to bun --- packages/bun/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/bun/src/index.ts b/packages/bun/src/index.ts index 2082f910403e..556f86e0d18e 100644 --- a/packages/bun/src/index.ts +++ b/packages/bun/src/index.ts @@ -125,6 +125,7 @@ export { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, + trpcMiddleware, } from '@sentry/node'; export { BunClient } from './client'; From 822a77c313ce9fb615d3ff6f6bd2d099c2adfc24 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Wed, 3 Apr 2024 11:17:35 +0000 Subject: [PATCH 3/4] docker compose --- .../suites/tracing/prisma-orm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-packages/node-integration-tests/suites/tracing/prisma-orm/package.json b/dev-packages/node-integration-tests/suites/tracing/prisma-orm/package.json index f8b24d7d0465..a83d6bfb312b 100644 --- a/dev-packages/node-integration-tests/suites/tracing/prisma-orm/package.json +++ b/dev-packages/node-integration-tests/suites/tracing/prisma-orm/package.json @@ -7,7 +7,7 @@ "node": ">=12" }, "scripts": { - "db-up": "docker-compose up -d", + "db-up": "docker compose up -d", "generate": "prisma generate", "migrate": "prisma migrate dev -n sentry-test", "setup": "run-s --silent db-up generate migrate" From cf073086bdce889328ff51383de7371913e1fda0 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Wed, 3 Apr 2024 11:26:58 +0000 Subject: [PATCH 4/4] another docker compose --- .../suites/tracing-new/prisma-orm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-packages/node-integration-tests/suites/tracing-new/prisma-orm/package.json b/dev-packages/node-integration-tests/suites/tracing-new/prisma-orm/package.json index f8b24d7d0465..a83d6bfb312b 100644 --- a/dev-packages/node-integration-tests/suites/tracing-new/prisma-orm/package.json +++ b/dev-packages/node-integration-tests/suites/tracing-new/prisma-orm/package.json @@ -7,7 +7,7 @@ "node": ">=12" }, "scripts": { - "db-up": "docker-compose up -d", + "db-up": "docker compose up -d", "generate": "prisma generate", "migrate": "prisma migrate dev -n sentry-test", "setup": "run-s --silent db-up generate migrate"