@@ -12,6 +12,14 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '
12
12
import { captureException } from '../exports' ;
13
13
import { SPAN_STATUS_ERROR , SPAN_STATUS_OK } from '../tracing' ;
14
14
15
+ export interface SupabaseClientConstructor {
16
+ prototype : {
17
+ from : ( table : string ) => PostgrestQueryBuilder ;
18
+ schema : ( schema : string ) => { rpc : ( ...args : unknown [ ] ) => Promise < unknown > } ;
19
+ } ;
20
+ rpc : ( fn : string , params : Record < string , unknown > ) => Promise < unknown > ;
21
+ }
22
+
15
23
const AUTH_OPERATIONS_TO_INSTRUMENT = [
16
24
'reauthenticate' ,
17
25
'signInAnonymously' ,
@@ -197,6 +205,76 @@ export function translateFiltersIntoMethods(key: string, query: string): string
197
205
return `${ method } (${ key } , ${ value . join ( '.' ) } )` ;
198
206
}
199
207
208
+ function instrumentRpcReturnedFromSchemaCall ( SupabaseClient : unknown ) : void {
209
+ ( SupabaseClient as unknown as SupabaseClientConstructor ) . prototype . schema = new Proxy (
210
+ ( SupabaseClient as unknown as SupabaseClientConstructor ) . prototype . schema ,
211
+ {
212
+ apply ( target , thisArg , argumentsList ) {
213
+ const rv = Reflect . apply ( target , thisArg , argumentsList ) ;
214
+
215
+ return instrumentRpc ( rv ) ;
216
+ } ,
217
+ } ,
218
+ ) ;
219
+ }
220
+
221
+ function instrumentRpc ( SupabaseClient : unknown ) : unknown {
222
+ ( SupabaseClient as unknown as SupabaseClientConstructor ) . rpc = new Proxy (
223
+ ( SupabaseClient as unknown as SupabaseClientConstructor ) . rpc ,
224
+ {
225
+ apply ( target , thisArg , argumentsList ) {
226
+ const isProducerSpan = argumentsList [ 0 ] === 'enqueue' ;
227
+ const isConsumerSpan = argumentsList [ 0 ] === 'dequeue' ;
228
+
229
+ const maybeQueueParams = argumentsList [ 1 ] ;
230
+
231
+ // If the second argument is not an object, it's not a queue operation
232
+ if ( ! isPlainObject ( maybeQueueParams ) ) {
233
+ return Reflect . apply ( target , thisArg , argumentsList ) ;
234
+ }
235
+
236
+ const msg = maybeQueueParams ?. msg as { title : string } ;
237
+
238
+ const messageId = msg ?. title ;
239
+ const queueName = maybeQueueParams ?. queue_name as string ;
240
+
241
+ const op = isProducerSpan ? 'queue.publish' : isConsumerSpan ? 'queue.process' : '' ;
242
+
243
+ // If the operation is not a queue operation, return the original function
244
+ if ( ! op ) {
245
+ return Reflect . apply ( target , thisArg , argumentsList ) ;
246
+ }
247
+
248
+ return startSpan (
249
+ {
250
+ name : 'supabase.db.rpc' ,
251
+ attributes : {
252
+ [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : 'auto.db.supabase' ,
253
+ [ SEMANTIC_ATTRIBUTE_SENTRY_OP ] : op ,
254
+ } ,
255
+ } ,
256
+ async span => {
257
+ return ( Reflect . apply ( target , thisArg , argumentsList ) as Promise < unknown > ) . then ( ( res : unknown ) => {
258
+ if ( messageId ) {
259
+ span . setAttribute ( 'messaging.message.id' , messageId ) ;
260
+ }
261
+
262
+ if ( queueName ) {
263
+ span . setAttribute ( 'messaging.destination.name' , queueName ) ;
264
+ }
265
+
266
+ span . end ( ) ;
267
+ return res ;
268
+ } ) ;
269
+ } ,
270
+ ) ;
271
+ } ,
272
+ } ,
273
+ ) ;
274
+
275
+ return SupabaseClient ;
276
+ }
277
+
200
278
function instrumentAuthOperation ( operation : AuthOperationFn , isAdmin = false ) : AuthOperationFn {
201
279
return new Proxy ( operation , {
202
280
apply ( target , thisArg , argumentsList ) {
@@ -266,13 +344,13 @@ function instrumentSupabaseAuthClient(supabaseClientInstance: SupabaseClientInst
266
344
} ) ;
267
345
}
268
346
269
- function instrumentSupabaseClientConstructor ( SupabaseClient : unknown ) : void {
270
- if ( instrumented . has ( SupabaseClient ) ) {
347
+ function instrumentSupabaseClientConstructor ( SupabaseClientConstructor : unknown ) : void {
348
+ if ( instrumented . has ( SupabaseClientConstructor ) ) {
271
349
return ;
272
350
}
273
351
274
- ( SupabaseClient as unknown as SupabaseClientConstructor ) . prototype . from = new Proxy (
275
- ( SupabaseClient as unknown as SupabaseClientConstructor ) . prototype . from ,
352
+ ( SupabaseClientConstructor as unknown as SupabaseClientConstructor ) . prototype . from = new Proxy (
353
+ ( SupabaseClientConstructor as unknown as SupabaseClientConstructor ) . prototype . from ,
276
354
{
277
355
apply ( target , thisArg , argumentsList ) {
278
356
const rv = Reflect . apply ( target , thisArg , argumentsList ) ;
@@ -466,6 +544,8 @@ const instrumentSupabase = (supabaseClientInstance: unknown): void => {
466
544
supabaseClientInstance . constructor === Function ? supabaseClientInstance : supabaseClientInstance . constructor ;
467
545
468
546
instrumentSupabaseClientConstructor ( SupabaseClientConstructor ) ;
547
+ instrumentRpcReturnedFromSchemaCall ( SupabaseClientConstructor ) ;
548
+ instrumentRpc ( supabaseClientInstance as SupabaseClientInstance ) ;
469
549
instrumentSupabaseAuthClient ( supabaseClientInstance as SupabaseClientInstance ) ;
470
550
} ;
471
551
0 commit comments