@@ -13,6 +13,14 @@ import { captureException } from '../exports';
13
13
import { SPAN_STATUS_ERROR , SPAN_STATUS_OK } from '../tracing' ;
14
14
import { DEBUG_BUILD } from '../debug-build' ;
15
15
16
+ export interface SupabaseClientConstructor {
17
+ prototype : {
18
+ from : ( table : string ) => PostgRESTQueryBuilder ;
19
+ schema : ( schema : string ) => { rpc : ( ...args : unknown [ ] ) => Promise < unknown > } ;
20
+ } ;
21
+ rpc : ( fn : string , params : Record < string , unknown > ) => Promise < unknown > ;
22
+ }
23
+
16
24
const AUTH_OPERATIONS_TO_INSTRUMENT = [
17
25
'reauthenticate' ,
18
26
'signInAnonymously' ,
@@ -114,12 +122,6 @@ export interface SupabaseBreadcrumb {
114
122
} ;
115
123
}
116
124
117
- export interface SupabaseClientConstructor {
118
- prototype : {
119
- from : ( table : string ) => PostgRESTQueryBuilder ;
120
- } ;
121
- }
122
-
123
125
export interface PostgRESTProtoThenable {
124
126
then : < T > (
125
127
onfulfilled ?: ( ( value : T ) => T | PromiseLike < T > ) | null ,
@@ -215,6 +217,76 @@ export function translateFiltersIntoMethods(key: string, query: string): string
215
217
return `${ method } (${ key } , ${ value . join ( '.' ) } )` ;
216
218
}
217
219
220
+ function instrumentRpcReturnedFromSchemaCall ( SupabaseClient : unknown ) : void {
221
+ ( SupabaseClient as unknown as SupabaseClientConstructor ) . prototype . schema = new Proxy (
222
+ ( SupabaseClient as unknown as SupabaseClientConstructor ) . prototype . schema ,
223
+ {
224
+ apply ( target , thisArg , argumentsList ) {
225
+ const rv = Reflect . apply ( target , thisArg , argumentsList ) ;
226
+
227
+ return instrumentRpc ( rv ) ;
228
+ } ,
229
+ } ,
230
+ ) ;
231
+ }
232
+
233
+ function instrumentRpc ( SupabaseClient : unknown ) : unknown {
234
+ ( SupabaseClient as unknown as SupabaseClientConstructor ) . rpc = new Proxy (
235
+ ( SupabaseClient as unknown as SupabaseClientConstructor ) . rpc ,
236
+ {
237
+ apply ( target , thisArg , argumentsList ) {
238
+ const isProducerSpan = argumentsList [ 0 ] === 'enqueue' ;
239
+ const isConsumerSpan = argumentsList [ 0 ] === 'dequeue' ;
240
+
241
+ const maybeQueueParams = argumentsList [ 1 ] ;
242
+
243
+ // If the second argument is not an object, it's not a queue operation
244
+ if ( ! isPlainObject ( maybeQueueParams ) ) {
245
+ return Reflect . apply ( target , thisArg , argumentsList ) ;
246
+ }
247
+
248
+ const msg = maybeQueueParams ?. msg as { title : string } ;
249
+
250
+ const messageId = msg ?. title ;
251
+ const queueName = maybeQueueParams ?. queue_name as string ;
252
+
253
+ const op = isProducerSpan ? 'queue.publish' : isConsumerSpan ? 'queue.process' : '' ;
254
+
255
+ // If the operation is not a queue operation, return the original function
256
+ if ( ! op ) {
257
+ return Reflect . apply ( target , thisArg , argumentsList ) ;
258
+ }
259
+
260
+ return startSpan (
261
+ {
262
+ name : 'supabase.db.rpc' ,
263
+ attributes : {
264
+ [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : 'auto.db.supabase' ,
265
+ [ SEMANTIC_ATTRIBUTE_SENTRY_OP ] : op ,
266
+ } ,
267
+ } ,
268
+ async span => {
269
+ return ( Reflect . apply ( target , thisArg , argumentsList ) as Promise < unknown > ) . then ( ( res : unknown ) => {
270
+ if ( messageId ) {
271
+ span . setAttribute ( 'messaging.message.id' , messageId ) ;
272
+ }
273
+
274
+ if ( queueName ) {
275
+ span . setAttribute ( 'messaging.destination.name' , queueName ) ;
276
+ }
277
+
278
+ span . end ( ) ;
279
+ return res ;
280
+ } ) ;
281
+ } ,
282
+ ) ;
283
+ } ,
284
+ } ,
285
+ ) ;
286
+
287
+ return SupabaseClient ;
288
+ }
289
+
218
290
function instrumentAuthOperation ( operation : AuthOperationFn , isAdmin = false ) : AuthOperationFn {
219
291
return new Proxy ( operation , {
220
292
apply ( target , thisArg , argumentsList ) {
@@ -496,6 +568,8 @@ export const instrumentSupabaseClient = (supabaseClient: unknown): void => {
496
568
supabaseClient . constructor === Function ? supabaseClient : supabaseClient . constructor ;
497
569
498
570
instrumentSupabaseClientConstructor ( SupabaseClientConstructor ) ;
571
+ instrumentRpcReturnedFromSchemaCall ( SupabaseClientConstructor ) ;
572
+ instrumentRpc ( supabaseClient as SupabaseClientInstance ) ;
499
573
instrumentSupabaseAuthClient ( supabaseClient as SupabaseClientInstance ) ;
500
574
} ;
501
575
0 commit comments