Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/sentry_sdk/integrations/__init__.py: 78%
70 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1"""This package"""
2from __future__ import absolute_import
4from threading import Lock
6from sentry_sdk._compat import iteritems
7from sentry_sdk.utils import logger
9from sentry_sdk._types import MYPY
11if MYPY: 11 ↛ 12line 11 didn't jump to line 12, because the condition on line 11 was never true
12 from typing import Callable
13 from typing import Dict
14 from typing import Iterator
15 from typing import List
16 from typing import Set
17 from typing import Tuple
18 from typing import Type
21_installer_lock = Lock()
22_installed_integrations = set() # type: Set[str]
25def _generate_default_integrations_iterator(integrations, auto_enabling_integrations):
26 # type: (Tuple[str, ...], Tuple[str, ...]) -> Callable[[bool], Iterator[Type[Integration]]]
28 def iter_default_integrations(with_auto_enabling_integrations):
29 # type: (bool) -> Iterator[Type[Integration]]
30 """Returns an iterator of the default integration classes:"""
31 from importlib import import_module
33 if with_auto_enabling_integrations: 33 ↛ 36line 33 didn't jump to line 36, because the condition on line 33 was never false
34 all_import_strings = integrations + auto_enabling_integrations
35 else:
36 all_import_strings = integrations
38 for import_string in all_import_strings:
39 try:
40 module, cls = import_string.rsplit(".", 1)
41 yield getattr(import_module(module), cls)
42 except (DidNotEnable, SyntaxError) as e:
43 logger.debug(
44 "Did not import default integration %s: %s", import_string, e
45 )
47 if isinstance(iter_default_integrations.__doc__, str): 47 ↛ 51line 47 didn't jump to line 51, because the condition on line 47 was never false
48 for import_string in integrations:
49 iter_default_integrations.__doc__ += "\n- `{}`".format(import_string)
51 return iter_default_integrations
54_AUTO_ENABLING_INTEGRATIONS = (
55 "sentry_sdk.integrations.django.DjangoIntegration",
56 "sentry_sdk.integrations.flask.FlaskIntegration",
57 "sentry_sdk.integrations.bottle.BottleIntegration",
58 "sentry_sdk.integrations.falcon.FalconIntegration",
59 "sentry_sdk.integrations.sanic.SanicIntegration",
60 "sentry_sdk.integrations.celery.CeleryIntegration",
61 "sentry_sdk.integrations.rq.RqIntegration",
62 "sentry_sdk.integrations.aiohttp.AioHttpIntegration",
63 "sentry_sdk.integrations.tornado.TornadoIntegration",
64 "sentry_sdk.integrations.sqlalchemy.SqlalchemyIntegration",
65 "sentry_sdk.integrations.redis.RedisIntegration",
66 "sentry_sdk.integrations.pyramid.PyramidIntegration",
67 "sentry_sdk.integrations.boto3.Boto3Integration",
68)
71iter_default_integrations = _generate_default_integrations_iterator(
72 integrations=(
73 # stdlib/base runtime integrations
74 "sentry_sdk.integrations.logging.LoggingIntegration",
75 "sentry_sdk.integrations.stdlib.StdlibIntegration",
76 "sentry_sdk.integrations.excepthook.ExcepthookIntegration",
77 "sentry_sdk.integrations.dedupe.DedupeIntegration",
78 "sentry_sdk.integrations.atexit.AtexitIntegration",
79 "sentry_sdk.integrations.modules.ModulesIntegration",
80 "sentry_sdk.integrations.argv.ArgvIntegration",
81 "sentry_sdk.integrations.threading.ThreadingIntegration",
82 ),
83 auto_enabling_integrations=_AUTO_ENABLING_INTEGRATIONS,
84)
86del _generate_default_integrations_iterator
89def setup_integrations(
90 integrations, with_defaults=True, with_auto_enabling_integrations=False
91):
92 # type: (List[Integration], bool, bool) -> Dict[str, Integration]
93 """Given a list of integration instances this installs them all. When
94 `with_defaults` is set to `True` then all default integrations are added
95 unless they were already provided before.
96 """
97 integrations = dict(
98 (integration.identifier, integration) for integration in integrations or ()
99 )
101 logger.debug("Setting up integrations (with default = %s)", with_defaults)
103 # Integrations that are not explicitly set up by the user.
104 used_as_default_integration = set()
106 if with_defaults: 106 ↛ 115line 106 didn't jump to line 115, because the condition on line 106 was never false
107 for integration_cls in iter_default_integrations(
108 with_auto_enabling_integrations
109 ):
110 if integration_cls.identifier not in integrations:
111 instance = integration_cls()
112 integrations[instance.identifier] = instance
113 used_as_default_integration.add(instance.identifier)
115 for identifier, integration in iteritems(integrations):
116 with _installer_lock:
117 if identifier not in _installed_integrations: 117 ↛ 115line 117 didn't jump to line 115, because the condition on line 117 was never false
118 logger.debug(
119 "Setting up previously not enabled integration %s", identifier
120 )
121 try:
122 type(integration).setup_once()
123 except NotImplementedError: 123 ↛ 124line 123 didn't jump to line 124, because the exception caught by line 123 didn't happen
124 if getattr(integration, "install", None) is not None:
125 logger.warning(
126 "Integration %s: The install method is "
127 "deprecated. Use `setup_once`.",
128 identifier,
129 )
130 integration.install()
131 else:
132 raise
133 except DidNotEnable as e:
134 if identifier not in used_as_default_integration: 134 ↛ 135line 134 didn't jump to line 135, because the condition on line 134 was never true
135 raise
137 logger.debug(
138 "Did not enable default integration %s: %s", identifier, e
139 )
141 _installed_integrations.add(identifier)
143 for identifier in integrations:
144 logger.debug("Enabling integration %s", identifier)
146 return integrations
149class DidNotEnable(Exception): # noqa: N818
150 """
151 The integration could not be enabled due to a trivial user error like
152 `flask` not being installed for the `FlaskIntegration`.
154 This exception is silently swallowed for default integrations, but reraised
155 for explicitly enabled integrations.
156 """
159class Integration(object):
160 """Baseclass for all integrations.
162 To accept options for an integration, implement your own constructor that
163 saves those options on `self`.
164 """
166 install = None
167 """Legacy method, do not implement."""
169 identifier = None # type: str
170 """String unique ID of integration type"""
172 @staticmethod
173 def setup_once():
174 # type: () -> None
175 """
176 Initialize the integration.
178 This function is only called once, ever. Configuration is not available
179 at this point, so the only thing to do here is to hook into exception
180 handlers, and perhaps do monkeypatches.
182 Inside those hooks `Integration.current` can be used to access the
183 instance again.
184 """
185 raise NotImplementedError()