diff --git a/sentry_sdk/integrations/__init__.py b/sentry_sdk/integrations/__init__.py index 2ab82f91e2..55dce10656 100644 --- a/sentry_sdk/integrations/__init__.py +++ b/sentry_sdk/integrations/__init__.py @@ -23,12 +23,14 @@ def get_default_integrations(): from sentry_sdk.integrations.excepthook import ExcepthookIntegration from sentry_sdk.integrations.dedupe import DedupeIntegration from sentry_sdk.integrations.atexit import AtexitIntegration + from sentry_sdk.integrations.modules import ModulesIntegration yield LoggingIntegration() yield StdlibIntegration() yield ExcepthookIntegration() yield DedupeIntegration() yield AtexitIntegration() + yield ModulesIntegration() def setup_integrations(integrations, with_defaults=True): diff --git a/sentry_sdk/integrations/modules.py b/sentry_sdk/integrations/modules.py new file mode 100644 index 0000000000..7b6250e7c5 --- /dev/null +++ b/sentry_sdk/integrations/modules.py @@ -0,0 +1,36 @@ +from __future__ import absolute_import + +from sentry_sdk.api import configure_scope +from sentry_sdk.integrations import Integration + +_installed_modules = None + + +def _generate_installed_modules(): + try: + import pkg_resources + except ImportError: + return + + for info in pkg_resources.working_set: + yield info.key, info.version + + +def _get_installed_modules(): + global _installed_modules + if _installed_modules is None: + _installed_modules = dict(_generate_installed_modules()) + return _installed_modules + + +class ModulesIntegration(Integration): + identifier = "modules" + + def install(self): + with configure_scope() as scope: + + @scope.add_event_processor + def processor(event, hint): + if "modules" not in event: + event["modules"] = dict(_get_installed_modules()) + return event diff --git a/tests/integrations/modules/test_modules.py b/tests/integrations/modules/test_modules.py new file mode 100644 index 0000000000..1529afc8e5 --- /dev/null +++ b/tests/integrations/modules/test_modules.py @@ -0,0 +1,14 @@ +import sentry_sdk + +from sentry_sdk.integrations.modules import ModulesIntegration + + +def test_basic(sentry_init, capture_events): + sentry_init(integrations=[ModulesIntegration()]) + events = capture_events() + + sentry_sdk.capture_exception(ValueError()) + + event, = events + assert "sentry-sdk" in event["modules"] + assert "pytest" in event["modules"]