Skip to content

Commit 357d6f5

Browse files
authored
feat(integrations): Add disabled_integrations (#3328)
Add a new init option called disabled_integrations, which is a sequence of integrations that will not be enabled regardless of what auto_enabling_integrations and default_integrations is set to.
1 parent c81c175 commit 357d6f5

File tree

5 files changed

+84
-16
lines changed

5 files changed

+84
-16
lines changed

sentry_sdk/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,6 @@ def _setup_instrumentation(self, functions_to_trace):
271271
function_obj = getattr(module_obj, function_name)
272272
setattr(module_obj, function_name, trace(function_obj))
273273
logger.debug("Enabled tracing for %s", function_qualname)
274-
275274
except module_not_found_error:
276275
try:
277276
# Try to import a class
@@ -372,6 +371,7 @@ def _capture_envelope(envelope):
372371
with_auto_enabling_integrations=self.options[
373372
"auto_enabling_integrations"
374373
],
374+
disabled_integrations=self.options["disabled_integrations"],
375375
)
376376

377377
self.spotlight = None

sentry_sdk/consts.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,7 @@ def __init__(
514514
profiles_sampler=None, # type: Optional[TracesSampler]
515515
profiler_mode=None, # type: Optional[ProfilerMode]
516516
auto_enabling_integrations=True, # type: bool
517+
disabled_integrations=None, # type: Optional[Sequence[Integration]]
517518
auto_session_tracking=True, # type: bool
518519
send_client_reports=True, # type: bool
519520
_experiments={}, # type: Experiments # noqa: B006

sentry_sdk/integrations/__init__.py

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66

77

88
if TYPE_CHECKING:
9+
from collections.abc import Sequence
910
from typing import Callable
1011
from typing import Dict
1112
from typing import Iterator
1213
from typing import List
14+
from typing import Optional
1315
from typing import Set
1416
from typing import Type
1517

@@ -114,21 +116,33 @@ def iter_default_integrations(with_auto_enabling_integrations):
114116

115117

116118
def setup_integrations(
117-
integrations, with_defaults=True, with_auto_enabling_integrations=False
119+
integrations,
120+
with_defaults=True,
121+
with_auto_enabling_integrations=False,
122+
disabled_integrations=None,
118123
):
119-
# type: (List[Integration], bool, bool) -> Dict[str, Integration]
124+
# type: (Sequence[Integration], bool, bool, Optional[Sequence[Integration]]) -> Dict[str, Integration]
120125
"""
121126
Given a list of integration instances, this installs them all.
122127
123128
When `with_defaults` is set to `True` all default integrations are added
124129
unless they were already provided before.
130+
131+
`disabled_integrations` takes precedence over `with_defaults` and
132+
`with_auto_enabling_integrations`.
125133
"""
126134
integrations = dict(
127135
(integration.identifier, integration) for integration in integrations or ()
128136
)
129137

130138
logger.debug("Setting up integrations (with default = %s)", with_defaults)
131139

140+
# Integrations that will not be enabled
141+
disabled_integrations = [
142+
integration if isinstance(integration, type) else type(integration)
143+
for integration in disabled_integrations or []
144+
]
145+
132146
# Integrations that are not explicitly set up by the user.
133147
used_as_default_integration = set()
134148

@@ -144,20 +158,23 @@ def setup_integrations(
144158
for identifier, integration in integrations.items():
145159
with _installer_lock:
146160
if identifier not in _processed_integrations:
147-
logger.debug(
148-
"Setting up previously not enabled integration %s", identifier
149-
)
150-
try:
151-
type(integration).setup_once()
152-
except DidNotEnable as e:
153-
if identifier not in used_as_default_integration:
154-
raise
155-
161+
if type(integration) in disabled_integrations:
162+
logger.debug("Ignoring integration %s", identifier)
163+
else:
156164
logger.debug(
157-
"Did not enable default integration %s: %s", identifier, e
165+
"Setting up previously not enabled integration %s", identifier
158166
)
159-
else:
160-
_installed_integrations.add(identifier)
167+
try:
168+
type(integration).setup_once()
169+
except DidNotEnable as e:
170+
if identifier not in used_as_default_integration:
171+
raise
172+
173+
logger.debug(
174+
"Did not enable default integration %s: %s", identifier, e
175+
)
176+
else:
177+
_installed_integrations.add(identifier)
161178

162179
_processed_integrations.add(identifier)
163180

tests/conftest.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from sentry_sdk.envelope import Envelope
2525
from sentry_sdk.integrations import ( # noqa: F401
2626
_DEFAULT_INTEGRATIONS,
27+
_installed_integrations,
2728
_processed_integrations,
2829
)
2930
from sentry_sdk.profiler import teardown_profiler
@@ -182,6 +183,7 @@ def reset_integrations():
182183
except ValueError:
183184
pass
184185
_processed_integrations.clear()
186+
_installed_integrations.clear()
185187

186188

187189
@pytest.fixture

tests/test_basics.py

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import datetime
2+
import importlib
23
import logging
34
import os
45
import sys
@@ -7,12 +8,12 @@
78

89
import pytest
910
from sentry_sdk.client import Client
10-
1111
from tests.conftest import patch_start_tracing_child
1212

1313
import sentry_sdk
1414
import sentry_sdk.scope
1515
from sentry_sdk import (
16+
get_client,
1617
push_scope,
1718
configure_scope,
1819
capture_event,
@@ -27,11 +28,13 @@
2728
)
2829
from sentry_sdk.integrations import (
2930
_AUTO_ENABLING_INTEGRATIONS,
31+
_DEFAULT_INTEGRATIONS,
3032
Integration,
3133
setup_integrations,
3234
)
3335
from sentry_sdk.integrations.logging import LoggingIntegration
3436
from sentry_sdk.integrations.redis import RedisIntegration
37+
from sentry_sdk.integrations.stdlib import StdlibIntegration
3538
from sentry_sdk.scope import add_global_event_processor
3639
from sentry_sdk.utils import get_sdk_name, reraise
3740
from sentry_sdk.tracing_utils import has_tracing_enabled
@@ -473,6 +476,51 @@ def test_integration_scoping(sentry_init, capture_events):
473476
assert not events
474477

475478

479+
default_integrations = [
480+
getattr(
481+
importlib.import_module(integration.rsplit(".", 1)[0]),
482+
integration.rsplit(".", 1)[1],
483+
)
484+
for integration in _DEFAULT_INTEGRATIONS
485+
]
486+
487+
488+
@pytest.mark.forked
489+
@pytest.mark.parametrize(
490+
"provided_integrations,default_integrations,disabled_integrations,expected_integrations",
491+
[
492+
([], False, None, set()),
493+
([], False, [], set()),
494+
([LoggingIntegration()], False, None, {LoggingIntegration}),
495+
([], True, None, set(default_integrations)),
496+
(
497+
[],
498+
True,
499+
[LoggingIntegration(), StdlibIntegration],
500+
set(default_integrations) - {LoggingIntegration, StdlibIntegration},
501+
),
502+
],
503+
)
504+
def test_integrations(
505+
sentry_init,
506+
provided_integrations,
507+
default_integrations,
508+
disabled_integrations,
509+
expected_integrations,
510+
reset_integrations,
511+
):
512+
sentry_init(
513+
integrations=provided_integrations,
514+
default_integrations=default_integrations,
515+
disabled_integrations=disabled_integrations,
516+
auto_enabling_integrations=False,
517+
debug=True,
518+
)
519+
assert {
520+
type(integration) for integration in get_client().integrations.values()
521+
} == expected_integrations
522+
523+
476524
@pytest.mark.skip(
477525
reason="This test is not valid anymore, because with the new Scopes calling bind_client on the Hub sets the client on the global scope. This test should be removed once the Hub is removed"
478526
)

0 commit comments

Comments
 (0)