@@ -13,13 +13,20 @@ import {
1313import type { Database , PreparedStatement } from 'db0' ;
1414// eslint-disable-next-line import/no-extraneous-dependencies
1515import { defineNitroPlugin , useDatabase } from 'nitropack/runtime' ;
16+ import type { DatabaseConnectionConfig as DatabaseConfig } from 'nitropack/types' ;
1617// @ts -expect-error - This is a virtual module
17- import { databaseInstances } from '#sentry/database-config.mjs' ;
18+ import { databaseConfig } from '#sentry/database-config.mjs' ;
19+ import { getDatabaseSpanData } from '../utils/database' ;
1820
1921type MaybeInstrumentedDatabase = Database & {
2022 __sentry_instrumented__ ?: boolean ;
2123} ;
2224
25+ interface DatabaseSpanData {
26+ [ key : string ] : string | undefined ;
27+ 'db.system.name' : string ;
28+ }
29+
2330/**
2431 * Keeps track of prepared statements that have been patched.
2532 */
@@ -35,12 +42,14 @@ const SENTRY_ORIGIN = 'auto.db.nuxt';
3542 */
3643export default defineNitroPlugin ( ( ) => {
3744 try {
45+ const _databaseConfig = databaseConfig as Record < string , DatabaseConfig > ;
46+ const databaseInstances = Object . keys ( databaseConfig ) ;
3847 debug . log ( '[Nitro Database Plugin]: Instrumenting databases...' ) ;
3948
4049 for ( const instance of databaseInstances ) {
4150 debug . log ( '[Nitro Database Plugin]: Instrumenting database instance:' , instance ) ;
4251 const db = useDatabase ( instance ) ;
43- instrumentDatabase ( db ) ;
52+ instrumentDatabase ( db , _databaseConfig [ instance ] ) ;
4453 }
4554
4655 debug . log ( '[Nitro Database Plugin]: Databases instrumented.' ) ;
@@ -55,17 +64,25 @@ export default defineNitroPlugin(() => {
5564 }
5665} ) ;
5766
58- function instrumentDatabase ( db : MaybeInstrumentedDatabase ) : void {
67+ /**
68+ * Instruments a database instance with Sentry.
69+ */
70+ function instrumentDatabase ( db : MaybeInstrumentedDatabase , config ?: DatabaseConfig ) : void {
5971 if ( db . __sentry_instrumented__ ) {
6072 debug . log ( '[Nitro Database Plugin]: Database already instrumented. Skipping...' ) ;
6173 return ;
6274 }
6375
76+ const metadata : DatabaseSpanData = {
77+ 'db.system.name' : config ?. connector ?? db . dialect ,
78+ ...getDatabaseSpanData ( config ) ,
79+ } ;
80+
6481 db . prepare = new Proxy ( db . prepare , {
6582 apply ( target , thisArg , args : Parameters < typeof db . prepare > ) {
6683 const [ query ] = args ;
6784
68- return instrumentPreparedStatement ( target . apply ( thisArg , args ) , query , db . dialect ) ;
85+ return instrumentPreparedStatement ( target . apply ( thisArg , args ) , query , metadata ) ;
6986 } ,
7087 } ) ;
7188
@@ -75,7 +92,7 @@ function instrumentDatabase(db: MaybeInstrumentedDatabase): void {
7592 db . sql = new Proxy ( db . sql , {
7693 apply ( target , thisArg , args : Parameters < typeof db . sql > ) {
7794 const query = args [ 0 ] ?. [ 0 ] ?? '' ;
78- const opts = createStartSpanOptions ( query , db . dialect ) ;
95+ const opts = createStartSpanOptions ( query , metadata ) ;
7996
8097 return startSpan (
8198 opts ,
@@ -87,7 +104,7 @@ function instrumentDatabase(db: MaybeInstrumentedDatabase): void {
87104 db . exec = new Proxy ( db . exec , {
88105 apply ( target , thisArg , args : Parameters < typeof db . exec > ) {
89106 return startSpan (
90- createStartSpanOptions ( args [ 0 ] , db . dialect ) ,
107+ createStartSpanOptions ( args [ 0 ] , metadata ) ,
91108 handleSpanStart ( ( ) => target . apply ( thisArg , args ) , { query : args [ 0 ] } ) ,
92109 ) ;
93110 } ,
@@ -102,16 +119,20 @@ function instrumentDatabase(db: MaybeInstrumentedDatabase): void {
102119 * This is meant to be used as a top-level call, under the hood it calls `instrumentPreparedStatementQueries`
103120 * to patch the query methods. The reason for this abstraction is to ensure that the `bind` method is also patched.
104121 */
105- function instrumentPreparedStatement ( statement : PreparedStatement , query : string , dialect : string ) : PreparedStatement {
122+ function instrumentPreparedStatement (
123+ statement : PreparedStatement ,
124+ query : string ,
125+ data : DatabaseSpanData ,
126+ ) : PreparedStatement {
106127 // statement.bind() returns a new instance of D1PreparedStatement, so we have to patch it as well.
107128 // eslint-disable-next-line @typescript-eslint/unbound-method
108129 statement . bind = new Proxy ( statement . bind , {
109130 apply ( target , thisArg , args : Parameters < typeof statement . bind > ) {
110- return instrumentPreparedStatementQueries ( target . apply ( thisArg , args ) , query , dialect ) ;
131+ return instrumentPreparedStatementQueries ( target . apply ( thisArg , args ) , query , data ) ;
111132 } ,
112133 } ) ;
113134
114- return instrumentPreparedStatementQueries ( statement , query , dialect ) ;
135+ return instrumentPreparedStatementQueries ( statement , query , data ) ;
115136}
116137
117138/**
@@ -120,7 +141,7 @@ function instrumentPreparedStatement(statement: PreparedStatement, query: string
120141function instrumentPreparedStatementQueries (
121142 statement : PreparedStatement ,
122143 query : string ,
123- dialect : string ,
144+ data : DatabaseSpanData ,
124145) : PreparedStatement {
125146 if ( patchedStatement . has ( statement ) ) {
126147 return statement ;
@@ -130,7 +151,7 @@ function instrumentPreparedStatementQueries(
130151 statement . get = new Proxy ( statement . get , {
131152 apply ( target , thisArg , args : Parameters < typeof statement . get > ) {
132153 return startSpan (
133- createStartSpanOptions ( query , dialect ) ,
154+ createStartSpanOptions ( query , data ) ,
134155 handleSpanStart ( ( ) => target . apply ( thisArg , args ) , { query } ) ,
135156 ) ;
136157 } ,
@@ -140,7 +161,7 @@ function instrumentPreparedStatementQueries(
140161 statement . run = new Proxy ( statement . run , {
141162 apply ( target , thisArg , args : Parameters < typeof statement . run > ) {
142163 return startSpan (
143- createStartSpanOptions ( query , dialect ) ,
164+ createStartSpanOptions ( query , data ) ,
144165 handleSpanStart ( ( ) => target . apply ( thisArg , args ) , { query } ) ,
145166 ) ;
146167 } ,
@@ -150,7 +171,7 @@ function instrumentPreparedStatementQueries(
150171 statement . all = new Proxy ( statement . all , {
151172 apply ( target , thisArg , args : Parameters < typeof statement . all > ) {
152173 return startSpan (
153- createStartSpanOptions ( query , dialect ) ,
174+ createStartSpanOptions ( query , data ) ,
154175 handleSpanStart ( ( ) => target . apply ( thisArg , args ) , { query } ) ,
155176 ) ;
156177 } ,
@@ -203,14 +224,14 @@ function createBreadcrumb(query: string): void {
203224/**
204225 * Creates a start span options object.
205226 */
206- function createStartSpanOptions ( query : string , dialect : string ) : StartSpanOptions {
227+ function createStartSpanOptions ( query : string , data : DatabaseSpanData ) : StartSpanOptions {
207228 return {
208229 name : query ,
209230 attributes : {
210- 'db.system.name' : dialect ,
211231 'db.query.text' : query ,
212232 [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : SENTRY_ORIGIN ,
213233 [ SEMANTIC_ATTRIBUTE_SENTRY_OP ] : 'db.query' ,
234+ ...data ,
214235 } ,
215236 } ;
216237}
0 commit comments