Skip to content

Improve user facing integrations configuration #4789

@timfish

Description

@timfish

Problem Statement

I've briefly chatted to @AbhiPrasad about this but we wanted to open the discussion up and get some feedback and ideas from others...

The current integration options are as follows:

  /**
   * If this is set to false, default integrations will not be added, otherwise this will internally be set to the
   * recommended default integrations.
   * TODO: We should consider changing this to `boolean | Integration[]`
   */
  defaultIntegrations?: false | Integration[];

  /**
   * List of integrations that should be installed after SDK was initialized.
   * Accepts either a list of integrations or a function that receives
   * default integrations and returns a new, updated list.
   */
  integrations?: Integration[] | ((integrations: Integration[]) => Integration[]);

There are a few issues I see with this:

  • defaultIntegrations: false is not tree shakeable.
  • It looks like defaultIntegrations allowing an array is an internal implementation detail that has leaked into the public api
    • it's not clear why users would ever supply an array here
  • It appears that the integrations function option solely exists to allow users to remove default integrations easily
    • Is there a better/cleaner way to offer this functionality?

Ultimately, we're stuck between a rock and hard place trying to provide a fully featured standard configuration, simple customisability and the ability to fully customise for those who want to reduce bundle size to the bare minimum.

Solution Brainstorm

We could remove defaultIntegrations and supply a way to init the SDKs without any defaults and preferably one that allows tree shaking.

The obvious way to do this would be to have two different init functions, one which includes the defaults and one which doesn't. For now I'm going to call these init and initRaw but I'm open to better suggestions!

It's also worth noting that initRaw could also include no default Transport to allow for greatest "tree shakeability".

import { init, initRaw, defaultIntegrations } from '@sentry/xxx';

// init the sdk with defaults
init({
   dsn: '__DSN__',
});

// this does the same as above!
initRaw({
   dsn: '__DSN__',
   integrations: defaultIntegrations,
})

Adding a custom integration:

import { init, initRaw, defaultIntegrations } from '@sentry/xxx';
import { MyWonderfulIntegration } from './integrations';

init({
   dsn: '__DSN__',
   integrations: [new MyWonderfulIntegration()]
});

initRaw({
   dsn: '__DSN__',
   integrations: [...defaultIntegrations, new MyWonderfulIntegration()],
})

Removing an integration:

import { init, initRaw, defaultIntegrations } from '@sentry/xxx';

init({
   dsn: '__DSN__',
   // this wont tree shake 🤷‍♂️
   integrations: (itgs) => itgs.filter(i => i.name !== "Breadcrumbs")
});

initRaw({
   dsn: '__DSN__',
   // this wont tree shake either 🤷‍♂️
   integrations: defaultIntegrations.filter(i => i.name !== "Breadcrumbs"),
})

initRaw({
   dsn: '__DSN__',
   integrations: [ /* manually include all the integrations you need for greatest tree shakability! */ ]
})

The integrations function option + filtering by name string to remove an integration feels a bit nasty but currently it appears to be the simplest solution to exclude an integration 🤔

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions