Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathtrpc.ts
More file actions
Latest commit
124 lines (111 loc) · 3.75 KB
/
Copy pathtrpc.ts
File metadata and controls
124 lines (111 loc) · 3.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import{
RPC_METHOD,
RPC_SYSTEM_NAME,
SENTRY_OP,
SENTRY_SEGMENT_NAME_SOURCE,
TRPC_PROCEDURE_PATH,
TRPC_PROCEDURE_TYPE,
}from'@sentry/conventions/attributes';
import{RPC}from'@sentry/conventions/op';
import{getClient,withIsolationScope}from'./currentScopes';
import{captureException}from'./exports';
import{SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN}from'./semanticAttributes';
import{startSpanManual}from'./tracing/trace';
import{normalize}from'./utils/normalize';
import{setNormalizationDepthOverrideHint}from'./utils/normalizationHints';
interfaceSentryTrpcMiddlewareOptions{
/** Whether to include procedure inputs in reported events. Defaults to `false`. */
attachRpcInput?: boolean;
forceTransaction?: boolean;
}
exportinterfaceSentryTrpcMiddlewareArguments<T>{
path?: unknown;
type?: unknown;
next: ()=>T;
rawInput?: unknown;
getRawInput?: ()=>Promise<unknown>;
}
consttrpcCaptureContext={mechanism: {handled: false,type: 'auto.rpc.trpc.middleware'}};
functioncaptureIfError(nextResult: unknown): void{
// TODO: Set span status based on what TRPCError was encountered
if(
typeofnextResult==='object'&&
nextResult!==null&&
'ok'innextResult&&
!nextResult.ok&&
'error'innextResult
){
captureException(nextResult.error,trpcCaptureContext);
}
}
typeSentryTrpcMiddleware<T>=TextendsPromise<unknown> ? T : Promise<T>;
/**
* Sentry tRPC middleware that captures errors and creates spans for tRPC procedures.
*/
exportfunctiontrpcMiddleware(options: SentryTrpcMiddlewareOptions={}){
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
returnasyncfunction<T>(opts: SentryTrpcMiddlewareArguments<T>): SentryTrpcMiddleware<T>{
const{ path, type, next, rawInput, getRawInput }=opts;
constclient=getClient();
constclientOptions=client?.getOptions();
constdataCollection=client?.getDataCollectionOptions();
consttrpcContext: Record<string,unknown>={
procedure_path: path,
procedure_type: type,
};
setNormalizationDepthOverrideHint(
trpcContext,
1+// 1 for context.input + the normal normalization depth
(clientOptions?.normalizeDepth??5),// 5 is a sane depth
);
if(
options.attachRpcInput!==undefined
? options.attachRpcInput
: dataCollection?.httpBodies.includes('incomingRequest')
){
if(rawInput!==undefined){
trpcContext.input=normalize(rawInput);
}
if(getRawInput!==undefined&&typeofgetRawInput==='function'){
try{
constrawRes=awaitgetRawInput();
trpcContext.input=normalize(rawRes);
}catch{
// noop
}
}
}
returnwithIsolationScope(scope=>{
scope.setContext('trpc',trpcContext);
returnstartSpanManual(
{
name: `trpc/${path}`,
attributes: {
[SENTRY_OP]: RPC,
[SENTRY_SEGMENT_NAME_SOURCE]: 'route',
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.rpc.trpc',
[RPC_SYSTEM_NAME]: 'trpc',
[RPC_METHOD]: String(path),
[TRPC_PROCEDURE_PATH]: String(path),
[TRPC_PROCEDURE_TYPE]: String(type),
},
// oxlint-disable-next-line typescript/no-deprecated
forceTransaction: !!options.forceTransaction,
},
asyncspan=>{
try{
constnextResult=awaitnext();
captureIfError(nextResult);
span.end();
returnnextResult;
}catch(e){
captureException(e,trpcCaptureContext);
span.end();
throwe;
}
},
)asSentryTrpcMiddleware<T>;
});
};
}