11import { getMainCarrier , Hub } from '@sentry/hub' ;
22import {
33 CustomSamplingContext ,
4+ Integration ,
5+ IntegrationClass ,
46 Options ,
57 SamplingContext ,
68 TransactionContext ,
79 TransactionSamplingMethod ,
810} from '@sentry/types' ;
9- import { logger } from '@sentry/utils' ;
11+ import { dynamicRequire , isNodeEnv , loadModule , logger } from '@sentry/utils' ;
1012
1113import { registerErrorInstrumentation } from './errors' ;
1214import { IdleTransaction } from './idletransaction' ;
@@ -206,15 +208,67 @@ export function startIdleTransaction(
206208 * @private
207209 */
208210export function _addTracingExtensions ( ) : void {
211+ // FIXME: This is problematic, because `getMainCarrier` always return a valid Carrier, but because
212+ // of how we set the types, we need to perform an unnecessary check here.
209213 const carrier = getMainCarrier ( ) ;
210- if ( carrier . __SENTRY__ ) {
211- carrier . __SENTRY__ . extensions = carrier . __SENTRY__ . extensions || { } ;
212- if ( ! carrier . __SENTRY__ . extensions . startTransaction ) {
213- carrier . __SENTRY__ . extensions . startTransaction = _startTransaction ;
214- }
215- if ( ! carrier . __SENTRY__ . extensions . traceHeaders ) {
216- carrier . __SENTRY__ . extensions . traceHeaders = traceHeaders ;
217- }
214+ if ( ! carrier . __SENTRY__ ) {
215+ return ;
216+ }
217+ carrier . __SENTRY__ . extensions = carrier . __SENTRY__ . extensions || { } ;
218+ if ( ! carrier . __SENTRY__ . extensions . startTransaction ) {
219+ carrier . __SENTRY__ . extensions . startTransaction = _startTransaction ;
220+ }
221+ if ( ! carrier . __SENTRY__ . extensions . traceHeaders ) {
222+ carrier . __SENTRY__ . extensions . traceHeaders = traceHeaders ;
223+ }
224+ }
225+
226+ /**
227+ * @private
228+ */
229+ function _autoloadDatabaseIntegrations ( ) : void {
230+ const carrier = getMainCarrier ( ) ;
231+ if ( ! carrier . __SENTRY__ ) {
232+ return ;
233+ }
234+
235+ const supportedPackages = [ 'mongodb' , 'mongoose' , 'pg' , 'mysql' ] ;
236+
237+ const packageToIntegrationMapping : Record < string , ( ) => Integration > = {
238+ mongodb ( ) {
239+ const integration = dynamicRequire ( module , './integrations/mongo' ) as { Mongo : IntegrationClass < Integration > } ;
240+ return new integration . Mongo ( ) ;
241+ } ,
242+ mongoose ( ) {
243+ const integration = dynamicRequire ( module , './integrations/mongo' ) as { Mongo : IntegrationClass < Integration > } ;
244+ return new integration . Mongo ( { mongoose : true } ) ;
245+ } ,
246+ mysql ( ) {
247+ const integration = dynamicRequire ( module , './integrations/mysql' ) as { Mysql : IntegrationClass < Integration > } ;
248+ return new integration . Mysql ( ) ;
249+ } ,
250+ pg ( ) {
251+ const integration = dynamicRequire ( module , './integrations/postgres' ) as {
252+ Postgres : IntegrationClass < Integration > ;
253+ } ;
254+ return new integration . Postgres ( ) ;
255+ } ,
256+ } ;
257+
258+ const mappedPackages = supportedPackages
259+ . filter ( moduleName => ! ! loadModule ( moduleName ) )
260+ . map ( pkg => {
261+ try {
262+ return packageToIntegrationMapping [ pkg ] ( ) ;
263+ } catch ( e ) {
264+ return undefined ;
265+ }
266+ } )
267+ . filter ( p => p ) as Integration [ ] ;
268+
269+ if ( mappedPackages . length > 0 ) {
270+ carrier . __SENTRY__ . integrations = carrier . __SENTRY__ . integrations || [ ] ;
271+ carrier . __SENTRY__ . integrations . concat ( mappedPackages ) ;
218272 }
219273}
220274
@@ -224,6 +278,12 @@ export function _addTracingExtensions(): void {
224278export function addExtensionMethods ( ) : void {
225279 _addTracingExtensions ( ) ;
226280
281+ // TODO: Option to disable this (but how, if it's a side-effect and there's no access to client options?)
282+ // Detect and automatically load specified integrations.
283+ if ( isNodeEnv ( ) ) {
284+ _autoloadDatabaseIntegrations ( ) ;
285+ }
286+
227287 // If an error happens globally, we should make sure transaction status is set to error.
228288 registerErrorInstrumentation ( ) ;
229289}
0 commit comments