@@ -149,6 +149,25 @@ function isInstrumented<T>(fn: T): boolean | undefined {
149149 }
150150}
151151
152+ /**
153+ * Plain-object bodies are copied into `plainBody`; array inserts (and other non-plain shapes) stay only on `rawBody`.
154+ * Returns a payload suitable for span attributes / breadcrumbs when the client has `sendDefaultPii` enabled.
155+ */
156+ function getMutationBodyPayloadForTelemetry ( rawBody : unknown , plainBody : Record < string , unknown > ) : unknown | undefined {
157+ if ( Object . keys ( plainBody ) . length > 0 ) {
158+ return plainBody ;
159+ }
160+ if ( Array . isArray ( rawBody ) && rawBody . length > 0 ) {
161+ return rawBody ;
162+ }
163+ return undefined ;
164+ }
165+
166+ /** True when the PostgREST builder carries a mutation body (for `insert(...)`, etc. in span descriptions). */
167+ function hasMutationBodyForDescription ( rawBody : unknown , plainBody : Record < string , unknown > ) : boolean {
168+ return getMutationBodyPayloadForTelemetry ( rawBody , plainBody ) !== undefined ;
169+ }
170+
152171/**
153172 * Extracts the database operation type from the HTTP method and headers
154173 * @param method - The HTTP method of the request
@@ -363,11 +382,15 @@ function instrumentPostgRESTFilterBuilder(PostgRESTFilterBuilder: PostgRESTFilte
363382 }
364383
365384 const sendDefaultPii = Boolean ( getClient ( ) ?. getOptions ( ) . sendDefaultPii ) ;
385+ const bodyPayload = getMutationBodyPayloadForTelemetry ( typedThis . body , body ) ;
366386
367387 // Adding operation to the beginning of the description if it's not a `select` operation
368388 // For example, it can be an `insert` or `update` operation but the query can be `select(...)`
369389 // For `select` operations, we don't need repeat it in the description
370- const mutationPart = operation === 'select' ? '' : `${ operation } ${ Object . keys ( body ) . length ? '(...) ' : '' } ` ;
390+ const mutationPart =
391+ operation === 'select'
392+ ? ''
393+ : `${ operation } ${ hasMutationBodyForDescription ( typedThis . body , body ) ? '(...) ' : '' } ` ;
371394 const queryPart = sendDefaultPii ? queryItems . join ( ' ' ) : queryItems . length > 0 ? '[redacted]' : '' ;
372395 const descriptionMiddle = [ mutationPart . trimEnd ( ) , queryPart ] . filter ( Boolean ) . join ( ' ' ) ;
373396 const description = descriptionMiddle ? `${ descriptionMiddle } from(${ table } )` : `from(${ table } )` ;
@@ -387,8 +410,8 @@ function instrumentPostgRESTFilterBuilder(PostgRESTFilterBuilder: PostgRESTFilte
387410 attributes [ 'db.query' ] = queryItems ;
388411 }
389412
390- if ( Object . keys ( body ) . length && sendDefaultPii ) {
391- attributes [ 'db.body' ] = body ;
413+ if ( bodyPayload !== undefined && sendDefaultPii ) {
414+ attributes [ 'db.body' ] = bodyPayload ;
392415 }
393416
394417 return startSpan (
@@ -420,8 +443,8 @@ function instrumentPostgRESTFilterBuilder(PostgRESTFilterBuilder: PostgRESTFilte
420443 if ( queryItems . length && sendDefaultPii ) {
421444 supabaseContext . query = queryItems ;
422445 }
423- if ( Object . keys ( body ) . length && sendDefaultPii ) {
424- supabaseContext . body = body ;
446+ if ( bodyPayload !== undefined && sendDefaultPii ) {
447+ supabaseContext . body = bodyPayload ;
425448 }
426449
427450 captureException ( err , scope => {
@@ -452,8 +475,8 @@ function instrumentPostgRESTFilterBuilder(PostgRESTFilterBuilder: PostgRESTFilte
452475 data . query = queryItems ;
453476 }
454477
455- if ( Object . keys ( body ) . length && sendDefaultPii ) {
456- data . body = body ;
478+ if ( bodyPayload !== undefined && sendDefaultPii ) {
479+ data . body = bodyPayload ;
457480 }
458481
459482 if ( Object . keys ( data ) . length ) {
0 commit comments