@@ -12,10 +12,14 @@ import {
1212} from '@sentry/core' ;
1313// eslint-disable-next-line import/no-extraneous-dependencies
1414import { defineNitroPlugin , useStorage } from 'nitropack/runtime' ;
15- import type { Driver } from 'unstorage' ;
15+ import type { Driver , Storage } from 'unstorage' ;
1616// @ts -expect-error - This is a virtual module
1717import { userStorageMounts } from '#sentry/storage-config.mjs' ;
1818
19+ type MaybeInstrumentedDriver = Driver & {
20+ __sentry_instrumented__ ?: boolean ;
21+ } ;
22+
1923/**
2024 * Creates a Nitro plugin that instruments the storage driver.
2125 */
@@ -35,24 +39,30 @@ export default defineNitroPlugin(async _nitroApp => {
3539 continue ;
3640 }
3741
38- debug . log ( `[Storage Instrumentation] Instrumenting mount: "${ mount . base } "` ) ;
39-
40- const driver = instrumentDriver ( mount . driver , mount . base ) ;
41-
4242 try {
43- // Remount with instrumented driver
44- await storage . unmount ( mount . base ) ;
45- await storage . mount ( mount . base , driver ) ;
43+ instrumentDriver ( mount . driver , mount . base ) ;
4644 } catch {
4745 debug . error ( `[Storage Instrumentation] Failed to unmount mount: "${ mount . base } "` ) ;
4846 }
47+
48+ // Wrap the mount method to instrument future mounts
49+ storage . mount = wrapStorageMount ( storage ) ;
4950 }
5051} ) ;
5152
5253/**
5354 * Instruments a driver by wrapping all method calls using proxies.
5455 */
55- function instrumentDriver ( driver : Driver , mountBase : string ) : Driver {
56+ function instrumentDriver ( driver : MaybeInstrumentedDriver , mountBase : string ) : Driver {
57+ // Already instrumented, skip...
58+ if ( driver . __sentry_instrumented__ ) {
59+ debug . log ( `[Storage Instrumentation] Driver already instrumented: "${ driver . name } ". Skipping...` ) ;
60+
61+ return driver ;
62+ }
63+
64+ debug . log ( `[Storage Instrumentation] Instrumenting driver: "${ driver . name } " on mount: "${ mountBase } "` ) ;
65+
5666 // List of driver methods to instrument
5767 const methodsToInstrument : ( keyof Driver ) [ ] = [
5868 'hasItem' ,
@@ -80,6 +90,9 @@ function instrumentDriver(driver: Driver, mountBase: string): Driver {
8090 driver [ methodName ] = createMethodWrapper ( original , methodName , driver . name ?? 'unknown' , mountBase ) ;
8191 }
8292
93+ // Mark as instrumented
94+ driver . __sentry_instrumented__ = true ;
95+
8396 return driver ;
8497}
8598
@@ -96,6 +109,8 @@ function createMethodWrapper(
96109 async apply ( target , thisArg , args ) {
97110 const attributes = getSpanAttributes ( methodName , driverName ?? 'unknown' , mountBase ) ;
98111
112+ debug . log ( `[Storage Instrumentation] Running method: "${ methodName } " on driver: "${ driverName } "` ) ;
113+
99114 return startSpan (
100115 {
101116 name : `storage.${ methodName } ` ,
@@ -127,6 +142,23 @@ function createMethodWrapper(
127142 } ) ;
128143}
129144
145+ /**
146+ * Wraps the storage mount method to instrument the driver.
147+ */
148+ function wrapStorageMount ( storage : Storage ) : Storage [ 'mount' ] {
149+ const original = storage . mount ;
150+
151+ function mountWithInstrumentation ( base : string , driver : Driver ) : Storage {
152+ debug . log ( `[Storage Instrumentation] Instrumenting mount: "${ base } "` ) ;
153+
154+ const instrumentedDriver = instrumentDriver ( driver , base ) ;
155+
156+ return original ( base , instrumentedDriver ) ;
157+ }
158+
159+ return mountWithInstrumentation ;
160+ }
161+
130162/**
131163 * Gets the span attributes for the storage method.
132164 */
0 commit comments