We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
aiohttp integration ability to use contextvars in logger 
Hi!

I was looking to add a custom [logging filter](https://docs.python.org/3/library/logging.html#logging.Filter) to my aiohttp server during exception that are catched [here](https://github.com/aio-libs/aiohttp/blob/16a49c143fc0abab75163fb78738fff3d3e17f49/aiohttp/web_protocol.py#L387).

It's useful and easy to do, but, it occurs that, in my custom logging filter, I can't find [contextvars](https://docs.python.org/3/library/contextvars.html) that I have created in my request handler task.

Two things caused this problem:
- [aiohttp handled requests in a sub-Task, and catched exceptions in the parent Task](https://github.com/aio-libs/aiohttp/blob/6a5ab96bd9cb404b4abfd5160fe8f34a29d941e5/aiohttp/web_protocol.py#L415-L416).
  → This was fixed in https://github.com/aio-libs/aiohttp/commit/9997cae (because users asked to be able to access `contextvars` -- like us). It was even [backported to aiohttp version 3.7](https://github.com/aio-libs/aiohttp/commit/29eccad84e8200b5c90856c8732da0fdbbcef904).
- [Sentry-aiohttp integration handles requests in a sub-Task too](https://github.com/getsentry/sentry-python/blob/cd646579d04e2fad6a8994304314ac52fec2f83c/sentry_sdk/integrations/aiohttp.py#L113).

Python documentation on Tasks [here](https://docs.python.org/3/library/asyncio-task.html#asyncio.Task). One important thing is that they reset *contextvars*.

To summarize:
```
   aiohttp                               logging exception
      +                                        ^
      |                                        |
      | asyncio.create_task(handle_request())  | contextvars didn't go up again
      |                                        | (it's fixed now)
      |                                        |
      v                                        |
   Sentry                                      |
      +                                        |
      |                                        |
      | asyncio.create_task(handle_request())  | contextvars don't go up
      |                                        |
      v                                        |
I set contextvars        +---------------------+

                                   Exception
```

As long as the issue is not fixed in Sentry, I still can't use `contextvars` to log custom data using the standard Python `logging` library.
The only solution is to disable Sentry, then logging works OK with contextvars.

Any idea how to fix this in Sentry-aiohttp code?
I'd be happy to open a PR, but I'm not familiar enough with Sentry code, or Python in general, thus I need some help at least.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `sentry_sdk/integrations/aiohttp.py`
Content:
```
1 import sys
2 import weakref
3 
4 from sentry_sdk._compat import reraise
5 from sentry_sdk.hub import Hub
6 from sentry_sdk.integrations import Integration, DidNotEnable
7 from sentry_sdk.integrations.logging import ignore_logger
8 from sentry_sdk.integrations._wsgi_common import (
9     _filter_headers,
10     request_body_within_bounds,
11 )
12 from sentry_sdk.tracing import Span
13 from sentry_sdk.utils import (
14     capture_internal_exceptions,
15     event_from_exception,
16     transaction_from_function,
17     HAS_REAL_CONTEXTVARS,
18     AnnotatedValue,
19 )
20 
21 try:
22     import asyncio
23 
24     from aiohttp import __version__ as AIOHTTP_VERSION
25     from aiohttp.web import Application, HTTPException, UrlDispatcher
26 except ImportError:
27     raise DidNotEnable("AIOHTTP not installed")
28 
29 from sentry_sdk._types import MYPY
30 
31 if MYPY:
32     from aiohttp.web_request import Request
33     from aiohttp.abc import AbstractMatchInfo
34     from typing import Any
35     from typing import Dict
36     from typing import Optional
37     from typing import Tuple
38     from typing import Callable
39     from typing import Union
40 
41     from sentry_sdk.utils import ExcInfo
42     from sentry_sdk._types import EventProcessor
43 
44 
45 class AioHttpIntegration(Integration):
46     identifier = "aiohttp"
47 
48     @staticmethod
49     def setup_once():
50         # type: () -> None
51 
52         try:
53             version = tuple(map(int, AIOHTTP_VERSION.split(".")))
54         except (TypeError, ValueError):
55             raise DidNotEnable("AIOHTTP version unparseable: {}".format(version))
56 
57         if version < (3, 4):
58             raise DidNotEnable("AIOHTTP 3.4 or newer required.")
59 
60         if not HAS_REAL_CONTEXTVARS:
61             # We better have contextvars or we're going to leak state between
62             # requests.
63             raise RuntimeError(
64                 "The aiohttp integration for Sentry requires Python 3.7+ "
65                 " or aiocontextvars package"
66             )
67 
68         ignore_logger("aiohttp.server")
69 
70         old_handle = Application._handle
71 
72         async def sentry_app_handle(self, request, *args, **kwargs):
73             # type: (Any, Request, *Any, **Any) -> Any
74             async def inner():
75                 # type: () -> Any
76                 hub = Hub.current
77                 if hub.get_integration(AioHttpIntegration) is None:
78                     return await old_handle(self, request, *args, **kwargs)
79 
80                 weak_request = weakref.ref(request)
81 
82                 with Hub(Hub.current) as hub:
83                     with hub.configure_scope() as scope:
84                         scope.clear_breadcrumbs()
85                         scope.add_event_processor(_make_request_processor(weak_request))
86 
87                     span = Span.continue_from_headers(request.headers)
88                     span.op = "http.server"
89                     # If this transaction name makes it to the UI, AIOHTTP's
90                     # URL resolver did not find a route or died trying.
91                     span.transaction = "generic AIOHTTP request"
92 
93                     with hub.start_span(span):
94                         try:
95                             response = await old_handle(self, request)
96                         except HTTPException as e:
97                             span.set_http_status(e.status_code)
98                             raise
99                         except asyncio.CancelledError:
100                             span.set_status("cancelled")
101                             raise
102                         except Exception:
103                             # This will probably map to a 500 but seems like we
104                             # have no way to tell. Do not set span status.
105                             reraise(*_capture_exception(hub))
106 
107                         span.set_http_status(response.status)
108                         return response
109 
110             # Explicitly wrap in task such that current contextvar context is
111             # copied. Just doing `return await inner()` will leak scope data
112             # between requests.
113             return await asyncio.get_event_loop().create_task(inner())
114 
115         Application._handle = sentry_app_handle
116 
117         old_urldispatcher_resolve = UrlDispatcher.resolve
118 
119         async def sentry_urldispatcher_resolve(self, request):
120             # type: (UrlDispatcher, Request) -> AbstractMatchInfo
121             rv = await old_urldispatcher_resolve(self, request)
122 
123             name = None
124 
125             try:
126                 name = transaction_from_function(rv.handler)
127             except Exception:
128                 pass
129 
130             if name is not None:
131                 with Hub.current.configure_scope() as scope:
132                     scope.transaction = name
133 
134             return rv
135 
136         UrlDispatcher.resolve = sentry_urldispatcher_resolve
137 
138 
139 def _make_request_processor(weak_request):
140     # type: (Callable[[], Request]) -> EventProcessor
141     def aiohttp_processor(
142         event,  # type: Dict[str, Any]
143         hint,  # type: Dict[str, Tuple[type, BaseException, Any]]
144     ):
145         # type: (...) -> Dict[str, Any]
146         request = weak_request()
147         if request is None:
148             return event
149 
150         with capture_internal_exceptions():
151             request_info = event.setdefault("request", {})
152 
153             request_info["url"] = "%s://%s%s" % (
154                 request.scheme,
155                 request.host,
156                 request.path,
157             )
158 
159             request_info["query_string"] = request.query_string
160             request_info["method"] = request.method
161             request_info["env"] = {"REMOTE_ADDR": request.remote}
162 
163             hub = Hub.current
164             request_info["headers"] = _filter_headers(dict(request.headers))
165 
166             # Just attach raw data here if it is within bounds, if available.
167             # Unfortunately there's no way to get structured data from aiohttp
168             # without awaiting on some coroutine.
169             request_info["data"] = get_aiohttp_request_data(hub, request)
170 
171         return event
172 
173     return aiohttp_processor
174 
175 
176 def _capture_exception(hub):
177     # type: (Hub) -> ExcInfo
178     exc_info = sys.exc_info()
179     event, hint = event_from_exception(
180         exc_info,
181         client_options=hub.client.options,  # type: ignore
182         mechanism={"type": "aiohttp", "handled": False},
183     )
184     hub.capture_event(event, hint=hint)
185     return exc_info
186 
187 
188 BODY_NOT_READ_MESSAGE = "[Can't show request body due to implementation details.]"
189 
190 
191 def get_aiohttp_request_data(hub, request):
192     # type: (Hub, Request) -> Union[Optional[str], AnnotatedValue]
193     bytes_body = request._read_bytes
194 
195     if bytes_body is not None:
196         # we have body to show
197         if not request_body_within_bounds(hub.client, len(bytes_body)):
198 
199             return AnnotatedValue(
200                 "",
201                 {"rem": [["!config", "x", 0, len(bytes_body)]], "len": len(bytes_body)},
202             )
203         encoding = request.charset or "utf-8"
204         return bytes_body.decode(encoding, "replace")
205 
206     if request.can_read_body:
207         # body exists but we can't show it
208         return BODY_NOT_READ_MESSAGE
209 
210     # request has no body
211     return None
212
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/sentry_sdk/integrations/aiohttp.py b/sentry_sdk/integrations/aiohttp.py
--- a/sentry_sdk/integrations/aiohttp.py
+++ b/sentry_sdk/integrations/aiohttp.py
@@ -71,46 +71,41 @@
 
         async def sentry_app_handle(self, request, *args, **kwargs):
             # type: (Any, Request, *Any, **Any) -> Any
-            async def inner():
-                # type: () -> Any
-                hub = Hub.current
-                if hub.get_integration(AioHttpIntegration) is None:
-                    return await old_handle(self, request, *args, **kwargs)
-
-                weak_request = weakref.ref(request)
-
-                with Hub(Hub.current) as hub:
-                    with hub.configure_scope() as scope:
-                        scope.clear_breadcrumbs()
-                        scope.add_event_processor(_make_request_processor(weak_request))
-
-                    span = Span.continue_from_headers(request.headers)
-                    span.op = "http.server"
-                    # If this transaction name makes it to the UI, AIOHTTP's
-                    # URL resolver did not find a route or died trying.
-                    span.transaction = "generic AIOHTTP request"
-
-                    with hub.start_span(span):
-                        try:
-                            response = await old_handle(self, request)
-                        except HTTPException as e:
-                            span.set_http_status(e.status_code)
-                            raise
-                        except asyncio.CancelledError:
-                            span.set_status("cancelled")
-                            raise
-                        except Exception:
-                            # This will probably map to a 500 but seems like we
-                            # have no way to tell. Do not set span status.
-                            reraise(*_capture_exception(hub))
-
-                        span.set_http_status(response.status)
-                        return response
-
-            # Explicitly wrap in task such that current contextvar context is
-            # copied. Just doing `return await inner()` will leak scope data
-            # between requests.
-            return await asyncio.get_event_loop().create_task(inner())
+            hub = Hub.current
+            if hub.get_integration(AioHttpIntegration) is None:
+                return await old_handle(self, request, *args, **kwargs)
+
+            weak_request = weakref.ref(request)
+
+            with Hub(Hub.current) as hub:
+                # Scope data will not leak between requests because aiohttp
+                # create a task to wrap each request.
+                with hub.configure_scope() as scope:
+                    scope.clear_breadcrumbs()
+                    scope.add_event_processor(_make_request_processor(weak_request))
+
+                span = Span.continue_from_headers(request.headers)
+                span.op = "http.server"
+                # If this transaction name makes it to the UI, AIOHTTP's
+                # URL resolver did not find a route or died trying.
+                span.transaction = "generic AIOHTTP request"
+
+                with hub.start_span(span):
+                    try:
+                        response = await old_handle(self, request)
+                    except HTTPException as e:
+                        span.set_http_status(e.status_code)
+                        raise
+                    except asyncio.CancelledError:
+                        span.set_status("cancelled")
+                        raise
+                    except Exception:
+                        # This will probably map to a 500 but seems like we
+                        # have no way to tell. Do not set span status.
+                        reraise(*_capture_exception(hub))
+
+                    span.set_http_status(response.status)
+                    return response
 
         Application._handle = sentry_app_handle

{"golden_diff": "diff --git a/sentry_sdk/integrations/aiohttp.py b/sentry_sdk/integrations/aiohttp.py\n--- a/sentry_sdk/integrations/aiohttp.py\n+++ b/sentry_sdk/integrations/aiohttp.py\n@@ -71,46 +71,41 @@\n \n         async def sentry_app_handle(self, request, *args, **kwargs):\n             # type: (Any, Request, *Any, **Any) -> Any\n-            async def inner():\n-                # type: () -> Any\n-                hub = Hub.current\n-                if hub.get_integration(AioHttpIntegration) is None:\n-                    return await old_handle(self, request, *args, **kwargs)\n-\n-                weak_request = weakref.ref(request)\n-\n-                with Hub(Hub.current) as hub:\n-                    with hub.configure_scope() as scope:\n-                        scope.clear_breadcrumbs()\n-                        scope.add_event_processor(_make_request_processor(weak_request))\n-\n-                    span = Span.continue_from_headers(request.headers)\n-                    span.op = \"http.server\"\n-                    # If this transaction name makes it to the UI, AIOHTTP's\n-                    # URL resolver did not find a route or died trying.\n-                    span.transaction = \"generic AIOHTTP request\"\n-\n-                    with hub.start_span(span):\n-                        try:\n-                            response = await old_handle(self, request)\n-                        except HTTPException as e:\n-                            span.set_http_status(e.status_code)\n-                            raise\n-                        except asyncio.CancelledError:\n-                            span.set_status(\"cancelled\")\n-                            raise\n-                        except Exception:\n-                            # This will probably map to a 500 but seems like we\n-                            # have no way to tell. Do not set span status.\n-                            reraise(*_capture_exception(hub))\n-\n-                        span.set_http_status(response.status)\n-                        return response\n-\n-            # Explicitly wrap in task such that current contextvar context is\n-            # copied. Just doing `return await inner()` will leak scope data\n-            # between requests.\n-            return await asyncio.get_event_loop().create_task(inner())\n+            hub = Hub.current\n+            if hub.get_integration(AioHttpIntegration) is None:\n+                return await old_handle(self, request, *args, **kwargs)\n+\n+            weak_request = weakref.ref(request)\n+\n+            with Hub(Hub.current) as hub:\n+                # Scope data will not leak between requests because aiohttp\n+                # create a task to wrap each request.\n+                with hub.configure_scope() as scope:\n+                    scope.clear_breadcrumbs()\n+                    scope.add_event_processor(_make_request_processor(weak_request))\n+\n+                span = Span.continue_from_headers(request.headers)\n+                span.op = \"http.server\"\n+                # If this transaction name makes it to the UI, AIOHTTP's\n+                # URL resolver did not find a route or died trying.\n+                span.transaction = \"generic AIOHTTP request\"\n+\n+                with hub.start_span(span):\n+                    try:\n+                        response = await old_handle(self, request)\n+                    except HTTPException as e:\n+                        span.set_http_status(e.status_code)\n+                        raise\n+                    except asyncio.CancelledError:\n+                        span.set_status(\"cancelled\")\n+                        raise\n+                    except Exception:\n+                        # This will probably map to a 500 but seems like we\n+                        # have no way to tell. Do not set span status.\n+                        reraise(*_capture_exception(hub))\n+\n+                    span.set_http_status(response.status)\n+                    return response\n \n         Application._handle = sentry_app_handle\n", "issue": "aiohttp integration ability to use contextvars in logger \nHi!\r\n\r\nI was looking to add a custom [logging filter](https://docs.python.org/3/library/logging.html#logging.Filter) to my aiohttp server during exception that are catched [here](https://github.com/aio-libs/aiohttp/blob/16a49c143fc0abab75163fb78738fff3d3e17f49/aiohttp/web_protocol.py#L387).\r\n\r\nIt's useful and easy to do, but, it occurs that, in my custom logging filter, I can't find [contextvars](https://docs.python.org/3/library/contextvars.html) that I have created in my request handler task.\r\n\r\nTwo things caused this problem:\r\n- [aiohttp handled requests in a sub-Task, and catched exceptions in the parent Task](https://github.com/aio-libs/aiohttp/blob/6a5ab96bd9cb404b4abfd5160fe8f34a29d941e5/aiohttp/web_protocol.py#L415-L416).\r\n  \u2192 This was fixed in https://github.com/aio-libs/aiohttp/commit/9997cae (because users asked to be able to access `contextvars` -- like us). It was even [backported to aiohttp version 3.7](https://github.com/aio-libs/aiohttp/commit/29eccad84e8200b5c90856c8732da0fdbbcef904).\r\n- [Sentry-aiohttp integration handles requests in a sub-Task too](https://github.com/getsentry/sentry-python/blob/cd646579d04e2fad6a8994304314ac52fec2f83c/sentry_sdk/integrations/aiohttp.py#L113).\r\n\r\nPython documentation on Tasks [here](https://docs.python.org/3/library/asyncio-task.html#asyncio.Task). One important thing is that they reset *contextvars*.\r\n\r\nTo summarize:\r\n```\r\n   aiohttp                               logging exception\r\n      +                                        ^\r\n      |                                        |\r\n      | asyncio.create_task(handle_request())  | contextvars didn't go up again\r\n      |                                        | (it's fixed now)\r\n      |                                        |\r\n      v                                        |\r\n   Sentry                                      |\r\n      +                                        |\r\n      |                                        |\r\n      | asyncio.create_task(handle_request())  | contextvars don't go up\r\n      |                                        |\r\n      v                                        |\r\nI set contextvars        +---------------------+\r\n\r\n                                   Exception\r\n```\r\n\r\nAs long as the issue is not fixed in Sentry, I still can't use `contextvars` to log custom data using the standard Python `logging` library.\r\nThe only solution is to disable Sentry, then logging works OK with contextvars.\r\n\r\nAny idea how to fix this in Sentry-aiohttp code?\r\nI'd be happy to open a PR, but I'm not familiar enough with Sentry code, or Python in general, thus I need some help at least.\n", "before_files": [{"content": "import sys\nimport weakref\n\nfrom sentry_sdk._compat import reraise\nfrom sentry_sdk.hub import Hub\nfrom sentry_sdk.integrations import Integration, DidNotEnable\nfrom sentry_sdk.integrations.logging import ignore_logger\nfrom sentry_sdk.integrations._wsgi_common import (\n    _filter_headers,\n    request_body_within_bounds,\n)\nfrom sentry_sdk.tracing import Span\nfrom sentry_sdk.utils import (\n    capture_internal_exceptions,\n    event_from_exception,\n    transaction_from_function,\n    HAS_REAL_CONTEXTVARS,\n    AnnotatedValue,\n)\n\ntry:\n    import asyncio\n\n    from aiohttp import __version__ as AIOHTTP_VERSION\n    from aiohttp.web import Application, HTTPException, UrlDispatcher\nexcept ImportError:\n    raise DidNotEnable(\"AIOHTTP not installed\")\n\nfrom sentry_sdk._types import MYPY\n\nif MYPY:\n    from aiohttp.web_request import Request\n    from aiohttp.abc import AbstractMatchInfo\n    from typing import Any\n    from typing import Dict\n    from typing import Optional\n    from typing import Tuple\n    from typing import Callable\n    from typing import Union\n\n    from sentry_sdk.utils import ExcInfo\n    from sentry_sdk._types import EventProcessor\n\n\nclass AioHttpIntegration(Integration):\n    identifier = \"aiohttp\"\n\n    @staticmethod\n    def setup_once():\n        # type: () -> None\n\n        try:\n            version = tuple(map(int, AIOHTTP_VERSION.split(\".\")))\n        except (TypeError, ValueError):\n            raise DidNotEnable(\"AIOHTTP version unparseable: {}\".format(version))\n\n        if version < (3, 4):\n            raise DidNotEnable(\"AIOHTTP 3.4 or newer required.\")\n\n        if not HAS_REAL_CONTEXTVARS:\n            # We better have contextvars or we're going to leak state between\n            # requests.\n            raise RuntimeError(\n                \"The aiohttp integration for Sentry requires Python 3.7+ \"\n                \" or aiocontextvars package\"\n            )\n\n        ignore_logger(\"aiohttp.server\")\n\n        old_handle = Application._handle\n\n        async def sentry_app_handle(self, request, *args, **kwargs):\n            # type: (Any, Request, *Any, **Any) -> Any\n            async def inner():\n                # type: () -> Any\n                hub = Hub.current\n                if hub.get_integration(AioHttpIntegration) is None:\n                    return await old_handle(self, request, *args, **kwargs)\n\n                weak_request = weakref.ref(request)\n\n                with Hub(Hub.current) as hub:\n                    with hub.configure_scope() as scope:\n                        scope.clear_breadcrumbs()\n                        scope.add_event_processor(_make_request_processor(weak_request))\n\n                    span = Span.continue_from_headers(request.headers)\n                    span.op = \"http.server\"\n                    # If this transaction name makes it to the UI, AIOHTTP's\n                    # URL resolver did not find a route or died trying.\n                    span.transaction = \"generic AIOHTTP request\"\n\n                    with hub.start_span(span):\n                        try:\n                            response = await old_handle(self, request)\n                        except HTTPException as e:\n                            span.set_http_status(e.status_code)\n                            raise\n                        except asyncio.CancelledError:\n                            span.set_status(\"cancelled\")\n                            raise\n                        except Exception:\n                            # This will probably map to a 500 but seems like we\n                            # have no way to tell. Do not set span status.\n                            reraise(*_capture_exception(hub))\n\n                        span.set_http_status(response.status)\n                        return response\n\n            # Explicitly wrap in task such that current contextvar context is\n            # copied. Just doing `return await inner()` will leak scope data\n            # between requests.\n            return await asyncio.get_event_loop().create_task(inner())\n\n        Application._handle = sentry_app_handle\n\n        old_urldispatcher_resolve = UrlDispatcher.resolve\n\n        async def sentry_urldispatcher_resolve(self, request):\n            # type: (UrlDispatcher, Request) -> AbstractMatchInfo\n            rv = await old_urldispatcher_resolve(self, request)\n\n            name = None\n\n            try:\n                name = transaction_from_function(rv.handler)\n            except Exception:\n                pass\n\n            if name is not None:\n                with Hub.current.configure_scope() as scope:\n                    scope.transaction = name\n\n            return rv\n\n        UrlDispatcher.resolve = sentry_urldispatcher_resolve\n\n\ndef _make_request_processor(weak_request):\n    # type: (Callable[[], Request]) -> EventProcessor\n    def aiohttp_processor(\n        event,  # type: Dict[str, Any]\n        hint,  # type: Dict[str, Tuple[type, BaseException, Any]]\n    ):\n        # type: (...) -> Dict[str, Any]\n        request = weak_request()\n        if request is None:\n            return event\n\n        with capture_internal_exceptions():\n            request_info = event.setdefault(\"request\", {})\n\n            request_info[\"url\"] = \"%s://%s%s\" % (\n                request.scheme,\n                request.host,\n                request.path,\n            )\n\n            request_info[\"query_string\"] = request.query_string\n            request_info[\"method\"] = request.method\n            request_info[\"env\"] = {\"REMOTE_ADDR\": request.remote}\n\n            hub = Hub.current\n            request_info[\"headers\"] = _filter_headers(dict(request.headers))\n\n            # Just attach raw data here if it is within bounds, if available.\n            # Unfortunately there's no way to get structured data from aiohttp\n            # without awaiting on some coroutine.\n            request_info[\"data\"] = get_aiohttp_request_data(hub, request)\n\n        return event\n\n    return aiohttp_processor\n\n\ndef _capture_exception(hub):\n    # type: (Hub) -> ExcInfo\n    exc_info = sys.exc_info()\n    event, hint = event_from_exception(\n        exc_info,\n        client_options=hub.client.options,  # type: ignore\n        mechanism={\"type\": \"aiohttp\", \"handled\": False},\n    )\n    hub.capture_event(event, hint=hint)\n    return exc_info\n\n\nBODY_NOT_READ_MESSAGE = \"[Can't show request body due to implementation details.]\"\n\n\ndef get_aiohttp_request_data(hub, request):\n    # type: (Hub, Request) -> Union[Optional[str], AnnotatedValue]\n    bytes_body = request._read_bytes\n\n    if bytes_body is not None:\n        # we have body to show\n        if not request_body_within_bounds(hub.client, len(bytes_body)):\n\n            return AnnotatedValue(\n                \"\",\n                {\"rem\": [[\"!config\", \"x\", 0, len(bytes_body)]], \"len\": len(bytes_body)},\n            )\n        encoding = request.charset or \"utf-8\"\n        return bytes_body.decode(encoding, \"replace\")\n\n    if request.can_read_body:\n        # body exists but we can't show it\n        return BODY_NOT_READ_MESSAGE\n\n    # request has no body\n    return None\n", "path": "sentry_sdk/integrations/aiohttp.py"}], "after_files": [{"content": "import sys\nimport weakref\n\nfrom sentry_sdk._compat import reraise\nfrom sentry_sdk.hub import Hub\nfrom sentry_sdk.integrations import Integration, DidNotEnable\nfrom sentry_sdk.integrations.logging import ignore_logger\nfrom sentry_sdk.integrations._wsgi_common import (\n    _filter_headers,\n    request_body_within_bounds,\n)\nfrom sentry_sdk.tracing import Span\nfrom sentry_sdk.utils import (\n    capture_internal_exceptions,\n    event_from_exception,\n    transaction_from_function,\n    HAS_REAL_CONTEXTVARS,\n    AnnotatedValue,\n)\n\ntry:\n    import asyncio\n\n    from aiohttp import __version__ as AIOHTTP_VERSION\n    from aiohttp.web import Application, HTTPException, UrlDispatcher\nexcept ImportError:\n    raise DidNotEnable(\"AIOHTTP not installed\")\n\nfrom sentry_sdk._types import MYPY\n\nif MYPY:\n    from aiohttp.web_request import Request\n    from aiohttp.abc import AbstractMatchInfo\n    from typing import Any\n    from typing import Dict\n    from typing import Optional\n    from typing import Tuple\n    from typing import Callable\n    from typing import Union\n\n    from sentry_sdk.utils import ExcInfo\n    from sentry_sdk._types import EventProcessor\n\n\nclass AioHttpIntegration(Integration):\n    identifier = \"aiohttp\"\n\n    @staticmethod\n    def setup_once():\n        # type: () -> None\n\n        try:\n            version = tuple(map(int, AIOHTTP_VERSION.split(\".\")))\n        except (TypeError, ValueError):\n            raise DidNotEnable(\"AIOHTTP version unparseable: {}\".format(version))\n\n        if version < (3, 4):\n            raise DidNotEnable(\"AIOHTTP 3.4 or newer required.\")\n\n        if not HAS_REAL_CONTEXTVARS:\n            # We better have contextvars or we're going to leak state between\n            # requests.\n            raise RuntimeError(\n                \"The aiohttp integration for Sentry requires Python 3.7+ \"\n                \" or aiocontextvars package\"\n            )\n\n        ignore_logger(\"aiohttp.server\")\n\n        old_handle = Application._handle\n\n        async def sentry_app_handle(self, request, *args, **kwargs):\n            # type: (Any, Request, *Any, **Any) -> Any\n            hub = Hub.current\n            if hub.get_integration(AioHttpIntegration) is None:\n                return await old_handle(self, request, *args, **kwargs)\n\n            weak_request = weakref.ref(request)\n\n            with Hub(Hub.current) as hub:\n                # Scope data will not leak between requests because aiohttp\n                # create a task to wrap each request.\n                with hub.configure_scope() as scope:\n                    scope.clear_breadcrumbs()\n                    scope.add_event_processor(_make_request_processor(weak_request))\n\n                span = Span.continue_from_headers(request.headers)\n                span.op = \"http.server\"\n                # If this transaction name makes it to the UI, AIOHTTP's\n                # URL resolver did not find a route or died trying.\n                span.transaction = \"generic AIOHTTP request\"\n\n                with hub.start_span(span):\n                    try:\n                        response = await old_handle(self, request)\n                    except HTTPException as e:\n                        span.set_http_status(e.status_code)\n                        raise\n                    except asyncio.CancelledError:\n                        span.set_status(\"cancelled\")\n                        raise\n                    except Exception:\n                        # This will probably map to a 500 but seems like we\n                        # have no way to tell. Do not set span status.\n                        reraise(*_capture_exception(hub))\n\n                    span.set_http_status(response.status)\n                    return response\n\n        Application._handle = sentry_app_handle\n\n        old_urldispatcher_resolve = UrlDispatcher.resolve\n\n        async def sentry_urldispatcher_resolve(self, request):\n            # type: (UrlDispatcher, Request) -> AbstractMatchInfo\n            rv = await old_urldispatcher_resolve(self, request)\n\n            name = None\n\n            try:\n                name = transaction_from_function(rv.handler)\n            except Exception:\n                pass\n\n            if name is not None:\n                with Hub.current.configure_scope() as scope:\n                    scope.transaction = name\n\n            return rv\n\n        UrlDispatcher.resolve = sentry_urldispatcher_resolve\n\n\ndef _make_request_processor(weak_request):\n    # type: (Callable[[], Request]) -> EventProcessor\n    def aiohttp_processor(\n        event,  # type: Dict[str, Any]\n        hint,  # type: Dict[str, Tuple[type, BaseException, Any]]\n    ):\n        # type: (...) -> Dict[str, Any]\n        request = weak_request()\n        if request is None:\n            return event\n\n        with capture_internal_exceptions():\n            request_info = event.setdefault(\"request\", {})\n\n            request_info[\"url\"] = \"%s://%s%s\" % (\n                request.scheme,\n                request.host,\n                request.path,\n            )\n\n            request_info[\"query_string\"] = request.query_string\n            request_info[\"method\"] = request.method\n            request_info[\"env\"] = {\"REMOTE_ADDR\": request.remote}\n\n            hub = Hub.current\n            request_info[\"headers\"] = _filter_headers(dict(request.headers))\n\n            # Just attach raw data here if it is within bounds, if available.\n            # Unfortunately there's no way to get structured data from aiohttp\n            # without awaiting on some coroutine.\n            request_info[\"data\"] = get_aiohttp_request_data(hub, request)\n\n        return event\n\n    return aiohttp_processor\n\n\ndef _capture_exception(hub):\n    # type: (Hub) -> ExcInfo\n    exc_info = sys.exc_info()\n    event, hint = event_from_exception(\n        exc_info,\n        client_options=hub.client.options,  # type: ignore\n        mechanism={\"type\": \"aiohttp\", \"handled\": False},\n    )\n    hub.capture_event(event, hint=hint)\n    return exc_info\n\n\nBODY_NOT_READ_MESSAGE = \"[Can't show request body due to implementation details.]\"\n\n\ndef get_aiohttp_request_data(hub, request):\n    # type: (Hub, Request) -> Union[Optional[str], AnnotatedValue]\n    bytes_body = request._read_bytes\n\n    if bytes_body is not None:\n        # we have body to show\n        if not request_body_within_bounds(hub.client, len(bytes_body)):\n\n            return AnnotatedValue(\n                \"\",\n                {\"rem\": [[\"!config\", \"x\", 0, len(bytes_body)]], \"len\": len(bytes_body)},\n            )\n        encoding = request.charset or \"utf-8\"\n        return bytes_body.decode(encoding, \"replace\")\n\n    if request.can_read_body:\n        # body exists but we can't show it\n        return BODY_NOT_READ_MESSAGE\n\n    # request has no body\n    return None\n", "path": "sentry_sdk/integrations/aiohttp.py"}]}