Repository: getsentry/sentry-python

Issue:
DjangoIntegration breaks Django Channels after reinitialization
After initializing Sentry, I'm using `sentry_sdk.init()` to disable error reporting in some cases. However, when using Django Channels and the Django integration, this breaks something in the Daphne webserver. After this second call to `init`, any request leads to the following error:

 ```
Traceback (most recent call last):
  File "<virtual env>/daphne/http_protocol.py", line 180, in process
    "server": self.server_addr,
TypeError: __call__() missing 1 required positional argument: 'send'

HTTP GET / 500 [0.01, 127.0.0.1:51170]
```

You can find a minimal example with that behaviour in [this repo](https://github.com/svenstucki/sentry-problem).

The problem seems to be that the second call is missing the `DjangoIntegration`, it goes away when passing a new instance.

This might seem like a weird use of the SDK, but there does not seem to be another way to disable error reporting after `init` was called. This approach was suggested [here](https://stackoverflow.com/a/52781369/182689) as a workaround, since it removes the DSN. It should definitely not break the application though or at least be documented.


Discussion:

Resolving patch:
diff --git a/sentry_sdk/integrations/django/__init__.py b/sentry_sdk/integrations/django/__init__.py
--- a/sentry_sdk/integrations/django/__init__.py
+++ b/sentry_sdk/integrations/django/__init__.py
@@ -298,22 +298,9 @@ def _patch_channels():
             "Python 3.7+ or the aiocontextvars package from PyPI."
         )
 
-    from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
+    from sentry_sdk.integrations.django.asgi import patch_channels_asgi_handler_impl
 
-    old_app = AsgiHandler.__call__
-
-    def sentry_patched_asgi_handler(self, receive, send):
-        # type: (AsgiHandler, Any, Any) -> Any
-        if Hub.current.get_integration(DjangoIntegration) is None:
-            return old_app(receive, send)
-
-        middleware = SentryAsgiMiddleware(
-            lambda _scope: old_app.__get__(self, AsgiHandler)
-        )
-
-        return middleware(self.scope)(receive, send)
-
-    AsgiHandler.__call__ = sentry_patched_asgi_handler
+    patch_channels_asgi_handler_impl(AsgiHandler)
 
 
 def _patch_django_asgi_handler():
diff --git a/sentry_sdk/integrations/django/asgi.py b/sentry_sdk/integrations/django/asgi.py
--- a/sentry_sdk/integrations/django/asgi.py
+++ b/sentry_sdk/integrations/django/asgi.py
@@ -29,3 +29,19 @@ async def sentry_patched_asgi_handler(self, scope, receive, send):
         return await middleware(scope, receive, send)
 
     cls.__call__ = sentry_patched_asgi_handler
+
+
+def patch_channels_asgi_handler_impl(cls):
+    # type: (Any) -> None
+    old_app = cls.__call__
+
+    async def sentry_patched_asgi_handler(self, receive, send):
+        # type: (Any, Any, Any) -> Any
+        if Hub.current.get_integration(DjangoIntegration) is None:
+            return await old_app(self, receive, send)
+
+        middleware = SentryAsgiMiddleware(lambda _scope: old_app.__get__(self, cls))
+
+        return await middleware(self.scope)(receive, send)
+
+    cls.__call__ = sentry_patched_asgi_handler


Test patch: