@@ -10,6 +10,7 @@ import {
10
10
extractTraceparentData ,
11
11
isString ,
12
12
logger ,
13
+ normalize ,
13
14
} from '@sentry/utils' ;
14
15
import * as domain from 'domain' ;
15
16
import type * as http from 'http' ;
@@ -315,6 +316,48 @@ export function errorHandler(options?: {
315
316
} ;
316
317
}
317
318
319
+ interface SentryTrpcMiddlewareOptions {
320
+ attachRpcInput ?: boolean ;
321
+ }
322
+
323
+ interface TrpcMiddlewareArguments < T > {
324
+ path : string ;
325
+ type : 'query' | 'mutation' | 'subscription' ;
326
+ next : ( ) => T ;
327
+ rawInput : unknown ;
328
+ }
329
+
330
+ /**
331
+ * Sentry tRPC middleware that names the handling transaction after the called procedure.
332
+ *
333
+ * Use the Sentry tRPC middleware in combination with the Sentry server integration,
334
+ * e.g. Express Request Handlers or Next.js SDK.
335
+ */
336
+ export async function trpcMiddleware ( options : SentryTrpcMiddlewareOptions = { } ) {
337
+ return function < T > ( { path, type, next, rawInput } : TrpcMiddlewareArguments < T > ) : T {
338
+ const hub = getCurrentHub ( ) ;
339
+ const clientOptions = hub . getClient ( ) ?. getOptions ( ) ;
340
+ const sentryTransaction = hub . getScope ( ) ?. getTransaction ( ) ;
341
+
342
+ if ( sentryTransaction ) {
343
+ sentryTransaction . setName ( `trcp/${ path } ` , 'route' ) ;
344
+ sentryTransaction . op = 'rpc.server' ;
345
+
346
+ const trpcData : Record < string , unknown > = {
347
+ procedureType : type ,
348
+ } ;
349
+
350
+ if ( options . attachRpcInput !== undefined ? options . attachRpcInput : clientOptions ?. sendDefaultPii ) {
351
+ trpcData . procedureInput = normalize ( rawInput ) ;
352
+ }
353
+
354
+ sentryTransaction . setData ( 'trpc' , trpcData ) ;
355
+ }
356
+
357
+ return next ( ) ;
358
+ } ;
359
+ }
360
+
318
361
// TODO (v8 / #5257): Remove this
319
362
// eslint-disable-next-line deprecation/deprecation
320
363
export type { ParseRequestOptions , ExpressRequest } from './requestDataDeprecated' ;
0 commit comments