We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
AWS Lambda under Python 3.8 is currently broken
It seems they have done some updates on the runtime that broke our integration.

--- 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/aws_lambda.py`
Content:
```
1 from datetime import datetime, timedelta
2 from os import environ
3 import sys
4 import json
5 
6 from sentry_sdk.hub import Hub, _should_send_default_pii
7 from sentry_sdk._compat import reraise
8 from sentry_sdk.utils import (
9     AnnotatedValue,
10     capture_internal_exceptions,
11     event_from_exception,
12     logger,
13     TimeoutThread,
14 )
15 from sentry_sdk.integrations import Integration
16 from sentry_sdk.integrations._wsgi_common import _filter_headers
17 
18 from sentry_sdk._types import MYPY
19 
20 if MYPY:
21     from typing import Any
22     from typing import TypeVar
23     from typing import Callable
24     from typing import Optional
25 
26     from sentry_sdk._types import EventProcessor, Event, Hint
27 
28     F = TypeVar("F", bound=Callable[..., Any])
29 
30 # Constants
31 TIMEOUT_WARNING_BUFFER = 1500  # Buffer time required to send timeout warning to Sentry
32 MILLIS_TO_SECONDS = 1000.0
33 
34 
35 def _wrap_init_error(init_error):
36     # type: (F) -> F
37     def sentry_init_error(*args, **kwargs):
38         # type: (*Any, **Any) -> Any
39 
40         hub = Hub.current
41         integration = hub.get_integration(AwsLambdaIntegration)
42         if integration is None:
43             return init_error(*args, **kwargs)
44 
45         # Fetch Initialization error details from arguments
46         error = json.loads(args[1])
47 
48         # If an integration is there, a client has to be there.
49         client = hub.client  # type: Any
50 
51         with hub.push_scope() as scope:
52             with capture_internal_exceptions():
53                 scope.clear_breadcrumbs()
54             # Checking if there is any error/exception which is raised in the runtime
55             # environment from arguments and, re-raising it to capture it as an event.
56             if error.get("errorType"):
57                 exc_info = sys.exc_info()
58                 event, hint = event_from_exception(
59                     exc_info,
60                     client_options=client.options,
61                     mechanism={"type": "aws_lambda", "handled": False},
62                 )
63                 hub.capture_event(event, hint=hint)
64 
65         return init_error(*args, **kwargs)
66 
67     return sentry_init_error  # type: ignore
68 
69 
70 def _wrap_handler(handler):
71     # type: (F) -> F
72     def sentry_handler(event, context, *args, **kwargs):
73         # type: (Any, Any, *Any, **Any) -> Any
74         hub = Hub.current
75         integration = hub.get_integration(AwsLambdaIntegration)
76         if integration is None:
77             return handler(event, context, *args, **kwargs)
78 
79         # If an integration is there, a client has to be there.
80         client = hub.client  # type: Any
81         configured_time = context.get_remaining_time_in_millis()
82 
83         with hub.push_scope() as scope:
84             with capture_internal_exceptions():
85                 scope.clear_breadcrumbs()
86                 scope.transaction = context.function_name
87                 scope.add_event_processor(
88                     _make_request_event_processor(event, context, configured_time)
89                 )
90                 # Starting the Timeout thread only if the configured time is greater than Timeout warning
91                 # buffer and timeout_warning parameter is set True.
92                 if (
93                     integration.timeout_warning
94                     and configured_time > TIMEOUT_WARNING_BUFFER
95                 ):
96                     waiting_time = (
97                         configured_time - TIMEOUT_WARNING_BUFFER
98                     ) / MILLIS_TO_SECONDS
99 
100                     timeout_thread = TimeoutThread(
101                         waiting_time, configured_time / MILLIS_TO_SECONDS
102                     )
103 
104                     # Starting the thread to raise timeout warning exception
105                     timeout_thread.start()
106 
107             try:
108                 return handler(event, context, *args, **kwargs)
109             except Exception:
110                 exc_info = sys.exc_info()
111                 event, hint = event_from_exception(
112                     exc_info,
113                     client_options=client.options,
114                     mechanism={"type": "aws_lambda", "handled": False},
115                 )
116                 hub.capture_event(event, hint=hint)
117                 reraise(*exc_info)
118 
119     return sentry_handler  # type: ignore
120 
121 
122 def _drain_queue():
123     # type: () -> None
124     with capture_internal_exceptions():
125         hub = Hub.current
126         integration = hub.get_integration(AwsLambdaIntegration)
127         if integration is not None:
128             # Flush out the event queue before AWS kills the
129             # process.
130             hub.flush()
131 
132 
133 class AwsLambdaIntegration(Integration):
134     identifier = "aws_lambda"
135 
136     def __init__(self, timeout_warning=False):
137         # type: (bool) -> None
138         self.timeout_warning = timeout_warning
139 
140     @staticmethod
141     def setup_once():
142         # type: () -> None
143         import __main__ as lambda_bootstrap  # type: ignore
144 
145         pre_37 = True  # Python 3.6 or 2.7
146 
147         if not hasattr(lambda_bootstrap, "handle_http_request"):
148             try:
149                 import bootstrap as lambda_bootstrap  # type: ignore
150 
151                 pre_37 = False  # Python 3.7
152             except ImportError:
153                 pass
154 
155         if not hasattr(lambda_bootstrap, "handle_event_request"):
156             logger.warning(
157                 "Not running in AWS Lambda environment, "
158                 "AwsLambdaIntegration disabled"
159             )
160             return
161 
162         if pre_37:
163             old_handle_event_request = lambda_bootstrap.handle_event_request
164 
165             def sentry_handle_event_request(request_handler, *args, **kwargs):
166                 # type: (Any, *Any, **Any) -> Any
167                 request_handler = _wrap_handler(request_handler)
168                 return old_handle_event_request(request_handler, *args, **kwargs)
169 
170             lambda_bootstrap.handle_event_request = sentry_handle_event_request
171 
172             old_handle_http_request = lambda_bootstrap.handle_http_request
173 
174             def sentry_handle_http_request(request_handler, *args, **kwargs):
175                 # type: (Any, *Any, **Any) -> Any
176                 request_handler = _wrap_handler(request_handler)
177                 return old_handle_http_request(request_handler, *args, **kwargs)
178 
179             lambda_bootstrap.handle_http_request = sentry_handle_http_request
180 
181             # Patch to_json to drain the queue. This should work even when the
182             # SDK is initialized inside of the handler
183 
184             old_to_json = lambda_bootstrap.to_json
185 
186             def sentry_to_json(*args, **kwargs):
187                 # type: (*Any, **Any) -> Any
188                 _drain_queue()
189                 return old_to_json(*args, **kwargs)
190 
191             lambda_bootstrap.to_json = sentry_to_json
192         else:
193             lambda_bootstrap.LambdaRuntimeClient.post_init_error = _wrap_init_error(
194                 lambda_bootstrap.LambdaRuntimeClient.post_init_error
195             )
196 
197             old_handle_event_request = lambda_bootstrap.handle_event_request
198 
199             def sentry_handle_event_request(  # type: ignore
200                 lambda_runtime_client, request_handler, *args, **kwargs
201             ):
202                 request_handler = _wrap_handler(request_handler)
203                 return old_handle_event_request(
204                     lambda_runtime_client, request_handler, *args, **kwargs
205                 )
206 
207             lambda_bootstrap.handle_event_request = sentry_handle_event_request
208 
209             # Patch the runtime client to drain the queue. This should work
210             # even when the SDK is initialized inside of the handler
211 
212             def _wrap_post_function(f):
213                 # type: (F) -> F
214                 def inner(*args, **kwargs):
215                     # type: (*Any, **Any) -> Any
216                     _drain_queue()
217                     return f(*args, **kwargs)
218 
219                 return inner  # type: ignore
220 
221             lambda_bootstrap.LambdaRuntimeClient.post_invocation_result = _wrap_post_function(
222                 lambda_bootstrap.LambdaRuntimeClient.post_invocation_result
223             )
224             lambda_bootstrap.LambdaRuntimeClient.post_invocation_error = _wrap_post_function(
225                 lambda_bootstrap.LambdaRuntimeClient.post_invocation_error
226             )
227 
228 
229 def _make_request_event_processor(aws_event, aws_context, configured_timeout):
230     # type: (Any, Any, Any) -> EventProcessor
231     start_time = datetime.now()
232 
233     def event_processor(event, hint, start_time=start_time):
234         # type: (Event, Hint, datetime) -> Optional[Event]
235         remaining_time_in_milis = aws_context.get_remaining_time_in_millis()
236         exec_duration = configured_timeout - remaining_time_in_milis
237 
238         extra = event.setdefault("extra", {})
239         extra["lambda"] = {
240             "function_name": aws_context.function_name,
241             "function_version": aws_context.function_version,
242             "invoked_function_arn": aws_context.invoked_function_arn,
243             "aws_request_id": aws_context.aws_request_id,
244             "execution_duration_in_millis": exec_duration,
245             "remaining_time_in_millis": remaining_time_in_milis,
246         }
247 
248         extra["cloudwatch logs"] = {
249             "url": _get_cloudwatch_logs_url(aws_context, start_time),
250             "log_group": aws_context.log_group_name,
251             "log_stream": aws_context.log_stream_name,
252         }
253 
254         request = event.get("request", {})
255 
256         if "httpMethod" in aws_event:
257             request["method"] = aws_event["httpMethod"]
258 
259         request["url"] = _get_url(aws_event, aws_context)
260 
261         if "queryStringParameters" in aws_event:
262             request["query_string"] = aws_event["queryStringParameters"]
263 
264         if "headers" in aws_event:
265             request["headers"] = _filter_headers(aws_event["headers"])
266 
267         if aws_event.get("body", None):
268             # Unfortunately couldn't find a way to get structured body from AWS
269             # event. Meaning every body is unstructured to us.
270             request["data"] = AnnotatedValue("", {"rem": [["!raw", "x", 0, 0]]})
271 
272         if _should_send_default_pii():
273             user_info = event.setdefault("user", {})
274 
275             id = aws_event.get("identity", {}).get("userArn")
276             if id is not None:
277                 user_info.setdefault("id", id)
278 
279             ip = aws_event.get("identity", {}).get("sourceIp")
280             if ip is not None:
281                 user_info.setdefault("ip_address", ip)
282 
283         event["request"] = request
284 
285         return event
286 
287     return event_processor
288 
289 
290 def _get_url(event, context):
291     # type: (Any, Any) -> str
292     path = event.get("path", None)
293     headers = event.get("headers", {})
294     host = headers.get("Host", None)
295     proto = headers.get("X-Forwarded-Proto", None)
296     if proto and host and path:
297         return "{}://{}{}".format(proto, host, path)
298     return "awslambda:///{}".format(context.function_name)
299 
300 
301 def _get_cloudwatch_logs_url(context, start_time):
302     # type: (Any, datetime) -> str
303     """
304     Generates a CloudWatchLogs console URL based on the context object
305 
306     Arguments:
307         context {Any} -- context from lambda handler
308 
309     Returns:
310         str -- AWS Console URL to logs.
311     """
312     formatstring = "%Y-%m-%dT%H:%M:%S"
313 
314     url = (
315         "https://console.aws.amazon.com/cloudwatch/home?region={region}"
316         "#logEventViewer:group={log_group};stream={log_stream}"
317         ";start={start_time};end={end_time}"
318     ).format(
319         region=environ.get("AWS_REGION"),
320         log_group=context.log_group_name,
321         log_stream=context.log_stream_name,
322         start_time=(start_time - timedelta(seconds=1)).strftime(formatstring),
323         end_time=(datetime.now() + timedelta(seconds=2)).strftime(formatstring),
324     )
325 
326     return url
327
```
--- 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/aws_lambda.py b/sentry_sdk/integrations/aws_lambda.py
--- a/sentry_sdk/integrations/aws_lambda.py
+++ b/sentry_sdk/integrations/aws_lambda.py
@@ -1,7 +1,6 @@
 from datetime import datetime, timedelta
 from os import environ
 import sys
-import json
 
 from sentry_sdk.hub import Hub, _should_send_default_pii
 from sentry_sdk._compat import reraise
@@ -42,19 +41,15 @@
         if integration is None:
             return init_error(*args, **kwargs)
 
-        # Fetch Initialization error details from arguments
-        error = json.loads(args[1])
-
         # If an integration is there, a client has to be there.
         client = hub.client  # type: Any
 
-        with hub.push_scope() as scope:
-            with capture_internal_exceptions():
+        with capture_internal_exceptions():
+            with hub.configure_scope() as scope:
                 scope.clear_breadcrumbs()
-            # Checking if there is any error/exception which is raised in the runtime
-            # environment from arguments and, re-raising it to capture it as an event.
-            if error.get("errorType"):
-                exc_info = sys.exc_info()
+
+            exc_info = sys.exc_info()
+            if exc_info and all(exc_info):
                 event, hint = event_from_exception(
                     exc_info,
                     client_options=client.options,
@@ -140,25 +135,39 @@
     @staticmethod
     def setup_once():
         # type: () -> None
-        import __main__ as lambda_bootstrap  # type: ignore
-
-        pre_37 = True  # Python 3.6 or 2.7
-
-        if not hasattr(lambda_bootstrap, "handle_http_request"):
-            try:
-                import bootstrap as lambda_bootstrap  # type: ignore
 
-                pre_37 = False  # Python 3.7
-            except ImportError:
-                pass
+        # Python 2.7: Everything is in `__main__`.
+        #
+        # Python 3.7: If the bootstrap module is *already imported*, it is the
+        # one we actually want to use (no idea what's in __main__)
+        #
+        # On Python 3.8 bootstrap is also importable, but will be the same file
+        # as __main__ imported under a different name:
+        #
+        #     sys.modules['__main__'].__file__ == sys.modules['bootstrap'].__file__
+        #     sys.modules['__main__'] is not sys.modules['bootstrap']
+        #
+        # Such a setup would then make all monkeypatches useless.
+        if "bootstrap" in sys.modules:
+            lambda_bootstrap = sys.modules["bootstrap"]  # type: Any
+        elif "__main__" in sys.modules:
+            lambda_bootstrap = sys.modules["__main__"]
+        else:
+            logger.warning(
+                "Not running in AWS Lambda environment, "
+                "AwsLambdaIntegration disabled (could not find bootstrap module)"
+            )
+            return
 
         if not hasattr(lambda_bootstrap, "handle_event_request"):
             logger.warning(
                 "Not running in AWS Lambda environment, "
-                "AwsLambdaIntegration disabled"
+                "AwsLambdaIntegration disabled (could not find handle_event_request)"
             )
             return
 
+        pre_37 = hasattr(lambda_bootstrap, "handle_http_request")  # Python 3.6 or 2.7
+
         if pre_37:
             old_handle_event_request = lambda_bootstrap.handle_event_request

{"golden_diff": "diff --git a/sentry_sdk/integrations/aws_lambda.py b/sentry_sdk/integrations/aws_lambda.py\n--- a/sentry_sdk/integrations/aws_lambda.py\n+++ b/sentry_sdk/integrations/aws_lambda.py\n@@ -1,7 +1,6 @@\n from datetime import datetime, timedelta\n from os import environ\n import sys\n-import json\n \n from sentry_sdk.hub import Hub, _should_send_default_pii\n from sentry_sdk._compat import reraise\n@@ -42,19 +41,15 @@\n         if integration is None:\n             return init_error(*args, **kwargs)\n \n-        # Fetch Initialization error details from arguments\n-        error = json.loads(args[1])\n-\n         # If an integration is there, a client has to be there.\n         client = hub.client  # type: Any\n \n-        with hub.push_scope() as scope:\n-            with capture_internal_exceptions():\n+        with capture_internal_exceptions():\n+            with hub.configure_scope() as scope:\n                 scope.clear_breadcrumbs()\n-            # Checking if there is any error/exception which is raised in the runtime\n-            # environment from arguments and, re-raising it to capture it as an event.\n-            if error.get(\"errorType\"):\n-                exc_info = sys.exc_info()\n+\n+            exc_info = sys.exc_info()\n+            if exc_info and all(exc_info):\n                 event, hint = event_from_exception(\n                     exc_info,\n                     client_options=client.options,\n@@ -140,25 +135,39 @@\n     @staticmethod\n     def setup_once():\n         # type: () -> None\n-        import __main__ as lambda_bootstrap  # type: ignore\n-\n-        pre_37 = True  # Python 3.6 or 2.7\n-\n-        if not hasattr(lambda_bootstrap, \"handle_http_request\"):\n-            try:\n-                import bootstrap as lambda_bootstrap  # type: ignore\n \n-                pre_37 = False  # Python 3.7\n-            except ImportError:\n-                pass\n+        # Python 2.7: Everything is in `__main__`.\n+        #\n+        # Python 3.7: If the bootstrap module is *already imported*, it is the\n+        # one we actually want to use (no idea what's in __main__)\n+        #\n+        # On Python 3.8 bootstrap is also importable, but will be the same file\n+        # as __main__ imported under a different name:\n+        #\n+        #     sys.modules['__main__'].__file__ == sys.modules['bootstrap'].__file__\n+        #     sys.modules['__main__'] is not sys.modules['bootstrap']\n+        #\n+        # Such a setup would then make all monkeypatches useless.\n+        if \"bootstrap\" in sys.modules:\n+            lambda_bootstrap = sys.modules[\"bootstrap\"]  # type: Any\n+        elif \"__main__\" in sys.modules:\n+            lambda_bootstrap = sys.modules[\"__main__\"]\n+        else:\n+            logger.warning(\n+                \"Not running in AWS Lambda environment, \"\n+                \"AwsLambdaIntegration disabled (could not find bootstrap module)\"\n+            )\n+            return\n \n         if not hasattr(lambda_bootstrap, \"handle_event_request\"):\n             logger.warning(\n                 \"Not running in AWS Lambda environment, \"\n-                \"AwsLambdaIntegration disabled\"\n+                \"AwsLambdaIntegration disabled (could not find handle_event_request)\"\n             )\n             return\n \n+        pre_37 = hasattr(lambda_bootstrap, \"handle_http_request\")  # Python 3.6 or 2.7\n+\n         if pre_37:\n             old_handle_event_request = lambda_bootstrap.handle_event_request\n", "issue": "AWS Lambda under Python 3.8 is currently broken\nIt seems they have done some updates on the runtime that broke our integration.\n", "before_files": [{"content": "from datetime import datetime, timedelta\nfrom os import environ\nimport sys\nimport json\n\nfrom sentry_sdk.hub import Hub, _should_send_default_pii\nfrom sentry_sdk._compat import reraise\nfrom sentry_sdk.utils import (\n    AnnotatedValue,\n    capture_internal_exceptions,\n    event_from_exception,\n    logger,\n    TimeoutThread,\n)\nfrom sentry_sdk.integrations import Integration\nfrom sentry_sdk.integrations._wsgi_common import _filter_headers\n\nfrom sentry_sdk._types import MYPY\n\nif MYPY:\n    from typing import Any\n    from typing import TypeVar\n    from typing import Callable\n    from typing import Optional\n\n    from sentry_sdk._types import EventProcessor, Event, Hint\n\n    F = TypeVar(\"F\", bound=Callable[..., Any])\n\n# Constants\nTIMEOUT_WARNING_BUFFER = 1500  # Buffer time required to send timeout warning to Sentry\nMILLIS_TO_SECONDS = 1000.0\n\n\ndef _wrap_init_error(init_error):\n    # type: (F) -> F\n    def sentry_init_error(*args, **kwargs):\n        # type: (*Any, **Any) -> Any\n\n        hub = Hub.current\n        integration = hub.get_integration(AwsLambdaIntegration)\n        if integration is None:\n            return init_error(*args, **kwargs)\n\n        # Fetch Initialization error details from arguments\n        error = json.loads(args[1])\n\n        # If an integration is there, a client has to be there.\n        client = hub.client  # type: Any\n\n        with hub.push_scope() as scope:\n            with capture_internal_exceptions():\n                scope.clear_breadcrumbs()\n            # Checking if there is any error/exception which is raised in the runtime\n            # environment from arguments and, re-raising it to capture it as an event.\n            if error.get(\"errorType\"):\n                exc_info = sys.exc_info()\n                event, hint = event_from_exception(\n                    exc_info,\n                    client_options=client.options,\n                    mechanism={\"type\": \"aws_lambda\", \"handled\": False},\n                )\n                hub.capture_event(event, hint=hint)\n\n        return init_error(*args, **kwargs)\n\n    return sentry_init_error  # type: ignore\n\n\ndef _wrap_handler(handler):\n    # type: (F) -> F\n    def sentry_handler(event, context, *args, **kwargs):\n        # type: (Any, Any, *Any, **Any) -> Any\n        hub = Hub.current\n        integration = hub.get_integration(AwsLambdaIntegration)\n        if integration is None:\n            return handler(event, context, *args, **kwargs)\n\n        # If an integration is there, a client has to be there.\n        client = hub.client  # type: Any\n        configured_time = context.get_remaining_time_in_millis()\n\n        with hub.push_scope() as scope:\n            with capture_internal_exceptions():\n                scope.clear_breadcrumbs()\n                scope.transaction = context.function_name\n                scope.add_event_processor(\n                    _make_request_event_processor(event, context, configured_time)\n                )\n                # Starting the Timeout thread only if the configured time is greater than Timeout warning\n                # buffer and timeout_warning parameter is set True.\n                if (\n                    integration.timeout_warning\n                    and configured_time > TIMEOUT_WARNING_BUFFER\n                ):\n                    waiting_time = (\n                        configured_time - TIMEOUT_WARNING_BUFFER\n                    ) / MILLIS_TO_SECONDS\n\n                    timeout_thread = TimeoutThread(\n                        waiting_time, configured_time / MILLIS_TO_SECONDS\n                    )\n\n                    # Starting the thread to raise timeout warning exception\n                    timeout_thread.start()\n\n            try:\n                return handler(event, context, *args, **kwargs)\n            except Exception:\n                exc_info = sys.exc_info()\n                event, hint = event_from_exception(\n                    exc_info,\n                    client_options=client.options,\n                    mechanism={\"type\": \"aws_lambda\", \"handled\": False},\n                )\n                hub.capture_event(event, hint=hint)\n                reraise(*exc_info)\n\n    return sentry_handler  # type: ignore\n\n\ndef _drain_queue():\n    # type: () -> None\n    with capture_internal_exceptions():\n        hub = Hub.current\n        integration = hub.get_integration(AwsLambdaIntegration)\n        if integration is not None:\n            # Flush out the event queue before AWS kills the\n            # process.\n            hub.flush()\n\n\nclass AwsLambdaIntegration(Integration):\n    identifier = \"aws_lambda\"\n\n    def __init__(self, timeout_warning=False):\n        # type: (bool) -> None\n        self.timeout_warning = timeout_warning\n\n    @staticmethod\n    def setup_once():\n        # type: () -> None\n        import __main__ as lambda_bootstrap  # type: ignore\n\n        pre_37 = True  # Python 3.6 or 2.7\n\n        if not hasattr(lambda_bootstrap, \"handle_http_request\"):\n            try:\n                import bootstrap as lambda_bootstrap  # type: ignore\n\n                pre_37 = False  # Python 3.7\n            except ImportError:\n                pass\n\n        if not hasattr(lambda_bootstrap, \"handle_event_request\"):\n            logger.warning(\n                \"Not running in AWS Lambda environment, \"\n                \"AwsLambdaIntegration disabled\"\n            )\n            return\n\n        if pre_37:\n            old_handle_event_request = lambda_bootstrap.handle_event_request\n\n            def sentry_handle_event_request(request_handler, *args, **kwargs):\n                # type: (Any, *Any, **Any) -> Any\n                request_handler = _wrap_handler(request_handler)\n                return old_handle_event_request(request_handler, *args, **kwargs)\n\n            lambda_bootstrap.handle_event_request = sentry_handle_event_request\n\n            old_handle_http_request = lambda_bootstrap.handle_http_request\n\n            def sentry_handle_http_request(request_handler, *args, **kwargs):\n                # type: (Any, *Any, **Any) -> Any\n                request_handler = _wrap_handler(request_handler)\n                return old_handle_http_request(request_handler, *args, **kwargs)\n\n            lambda_bootstrap.handle_http_request = sentry_handle_http_request\n\n            # Patch to_json to drain the queue. This should work even when the\n            # SDK is initialized inside of the handler\n\n            old_to_json = lambda_bootstrap.to_json\n\n            def sentry_to_json(*args, **kwargs):\n                # type: (*Any, **Any) -> Any\n                _drain_queue()\n                return old_to_json(*args, **kwargs)\n\n            lambda_bootstrap.to_json = sentry_to_json\n        else:\n            lambda_bootstrap.LambdaRuntimeClient.post_init_error = _wrap_init_error(\n                lambda_bootstrap.LambdaRuntimeClient.post_init_error\n            )\n\n            old_handle_event_request = lambda_bootstrap.handle_event_request\n\n            def sentry_handle_event_request(  # type: ignore\n                lambda_runtime_client, request_handler, *args, **kwargs\n            ):\n                request_handler = _wrap_handler(request_handler)\n                return old_handle_event_request(\n                    lambda_runtime_client, request_handler, *args, **kwargs\n                )\n\n            lambda_bootstrap.handle_event_request = sentry_handle_event_request\n\n            # Patch the runtime client to drain the queue. This should work\n            # even when the SDK is initialized inside of the handler\n\n            def _wrap_post_function(f):\n                # type: (F) -> F\n                def inner(*args, **kwargs):\n                    # type: (*Any, **Any) -> Any\n                    _drain_queue()\n                    return f(*args, **kwargs)\n\n                return inner  # type: ignore\n\n            lambda_bootstrap.LambdaRuntimeClient.post_invocation_result = _wrap_post_function(\n                lambda_bootstrap.LambdaRuntimeClient.post_invocation_result\n            )\n            lambda_bootstrap.LambdaRuntimeClient.post_invocation_error = _wrap_post_function(\n                lambda_bootstrap.LambdaRuntimeClient.post_invocation_error\n            )\n\n\ndef _make_request_event_processor(aws_event, aws_context, configured_timeout):\n    # type: (Any, Any, Any) -> EventProcessor\n    start_time = datetime.now()\n\n    def event_processor(event, hint, start_time=start_time):\n        # type: (Event, Hint, datetime) -> Optional[Event]\n        remaining_time_in_milis = aws_context.get_remaining_time_in_millis()\n        exec_duration = configured_timeout - remaining_time_in_milis\n\n        extra = event.setdefault(\"extra\", {})\n        extra[\"lambda\"] = {\n            \"function_name\": aws_context.function_name,\n            \"function_version\": aws_context.function_version,\n            \"invoked_function_arn\": aws_context.invoked_function_arn,\n            \"aws_request_id\": aws_context.aws_request_id,\n            \"execution_duration_in_millis\": exec_duration,\n            \"remaining_time_in_millis\": remaining_time_in_milis,\n        }\n\n        extra[\"cloudwatch logs\"] = {\n            \"url\": _get_cloudwatch_logs_url(aws_context, start_time),\n            \"log_group\": aws_context.log_group_name,\n            \"log_stream\": aws_context.log_stream_name,\n        }\n\n        request = event.get(\"request\", {})\n\n        if \"httpMethod\" in aws_event:\n            request[\"method\"] = aws_event[\"httpMethod\"]\n\n        request[\"url\"] = _get_url(aws_event, aws_context)\n\n        if \"queryStringParameters\" in aws_event:\n            request[\"query_string\"] = aws_event[\"queryStringParameters\"]\n\n        if \"headers\" in aws_event:\n            request[\"headers\"] = _filter_headers(aws_event[\"headers\"])\n\n        if aws_event.get(\"body\", None):\n            # Unfortunately couldn't find a way to get structured body from AWS\n            # event. Meaning every body is unstructured to us.\n            request[\"data\"] = AnnotatedValue(\"\", {\"rem\": [[\"!raw\", \"x\", 0, 0]]})\n\n        if _should_send_default_pii():\n            user_info = event.setdefault(\"user\", {})\n\n            id = aws_event.get(\"identity\", {}).get(\"userArn\")\n            if id is not None:\n                user_info.setdefault(\"id\", id)\n\n            ip = aws_event.get(\"identity\", {}).get(\"sourceIp\")\n            if ip is not None:\n                user_info.setdefault(\"ip_address\", ip)\n\n        event[\"request\"] = request\n\n        return event\n\n    return event_processor\n\n\ndef _get_url(event, context):\n    # type: (Any, Any) -> str\n    path = event.get(\"path\", None)\n    headers = event.get(\"headers\", {})\n    host = headers.get(\"Host\", None)\n    proto = headers.get(\"X-Forwarded-Proto\", None)\n    if proto and host and path:\n        return \"{}://{}{}\".format(proto, host, path)\n    return \"awslambda:///{}\".format(context.function_name)\n\n\ndef _get_cloudwatch_logs_url(context, start_time):\n    # type: (Any, datetime) -> str\n    \"\"\"\n    Generates a CloudWatchLogs console URL based on the context object\n\n    Arguments:\n        context {Any} -- context from lambda handler\n\n    Returns:\n        str -- AWS Console URL to logs.\n    \"\"\"\n    formatstring = \"%Y-%m-%dT%H:%M:%S\"\n\n    url = (\n        \"https://console.aws.amazon.com/cloudwatch/home?region={region}\"\n        \"#logEventViewer:group={log_group};stream={log_stream}\"\n        \";start={start_time};end={end_time}\"\n    ).format(\n        region=environ.get(\"AWS_REGION\"),\n        log_group=context.log_group_name,\n        log_stream=context.log_stream_name,\n        start_time=(start_time - timedelta(seconds=1)).strftime(formatstring),\n        end_time=(datetime.now() + timedelta(seconds=2)).strftime(formatstring),\n    )\n\n    return url\n", "path": "sentry_sdk/integrations/aws_lambda.py"}], "after_files": [{"content": "from datetime import datetime, timedelta\nfrom os import environ\nimport sys\n\nfrom sentry_sdk.hub import Hub, _should_send_default_pii\nfrom sentry_sdk._compat import reraise\nfrom sentry_sdk.utils import (\n    AnnotatedValue,\n    capture_internal_exceptions,\n    event_from_exception,\n    logger,\n    TimeoutThread,\n)\nfrom sentry_sdk.integrations import Integration\nfrom sentry_sdk.integrations._wsgi_common import _filter_headers\n\nfrom sentry_sdk._types import MYPY\n\nif MYPY:\n    from typing import Any\n    from typing import TypeVar\n    from typing import Callable\n    from typing import Optional\n\n    from sentry_sdk._types import EventProcessor, Event, Hint\n\n    F = TypeVar(\"F\", bound=Callable[..., Any])\n\n# Constants\nTIMEOUT_WARNING_BUFFER = 1500  # Buffer time required to send timeout warning to Sentry\nMILLIS_TO_SECONDS = 1000.0\n\n\ndef _wrap_init_error(init_error):\n    # type: (F) -> F\n    def sentry_init_error(*args, **kwargs):\n        # type: (*Any, **Any) -> Any\n\n        hub = Hub.current\n        integration = hub.get_integration(AwsLambdaIntegration)\n        if integration is None:\n            return init_error(*args, **kwargs)\n\n        # If an integration is there, a client has to be there.\n        client = hub.client  # type: Any\n\n        with capture_internal_exceptions():\n            with hub.configure_scope() as scope:\n                scope.clear_breadcrumbs()\n\n            exc_info = sys.exc_info()\n            if exc_info and all(exc_info):\n                event, hint = event_from_exception(\n                    exc_info,\n                    client_options=client.options,\n                    mechanism={\"type\": \"aws_lambda\", \"handled\": False},\n                )\n                hub.capture_event(event, hint=hint)\n\n        return init_error(*args, **kwargs)\n\n    return sentry_init_error  # type: ignore\n\n\ndef _wrap_handler(handler):\n    # type: (F) -> F\n    def sentry_handler(event, context, *args, **kwargs):\n        # type: (Any, Any, *Any, **Any) -> Any\n        hub = Hub.current\n        integration = hub.get_integration(AwsLambdaIntegration)\n        if integration is None:\n            return handler(event, context, *args, **kwargs)\n\n        # If an integration is there, a client has to be there.\n        client = hub.client  # type: Any\n        configured_time = context.get_remaining_time_in_millis()\n\n        with hub.push_scope() as scope:\n            with capture_internal_exceptions():\n                scope.clear_breadcrumbs()\n                scope.transaction = context.function_name\n                scope.add_event_processor(\n                    _make_request_event_processor(event, context, configured_time)\n                )\n                # Starting the Timeout thread only if the configured time is greater than Timeout warning\n                # buffer and timeout_warning parameter is set True.\n                if (\n                    integration.timeout_warning\n                    and configured_time > TIMEOUT_WARNING_BUFFER\n                ):\n                    waiting_time = (\n                        configured_time - TIMEOUT_WARNING_BUFFER\n                    ) / MILLIS_TO_SECONDS\n\n                    timeout_thread = TimeoutThread(\n                        waiting_time, configured_time / MILLIS_TO_SECONDS\n                    )\n\n                    # Starting the thread to raise timeout warning exception\n                    timeout_thread.start()\n\n            try:\n                return handler(event, context, *args, **kwargs)\n            except Exception:\n                exc_info = sys.exc_info()\n                event, hint = event_from_exception(\n                    exc_info,\n                    client_options=client.options,\n                    mechanism={\"type\": \"aws_lambda\", \"handled\": False},\n                )\n                hub.capture_event(event, hint=hint)\n                reraise(*exc_info)\n\n    return sentry_handler  # type: ignore\n\n\ndef _drain_queue():\n    # type: () -> None\n    with capture_internal_exceptions():\n        hub = Hub.current\n        integration = hub.get_integration(AwsLambdaIntegration)\n        if integration is not None:\n            # Flush out the event queue before AWS kills the\n            # process.\n            hub.flush()\n\n\nclass AwsLambdaIntegration(Integration):\n    identifier = \"aws_lambda\"\n\n    def __init__(self, timeout_warning=False):\n        # type: (bool) -> None\n        self.timeout_warning = timeout_warning\n\n    @staticmethod\n    def setup_once():\n        # type: () -> None\n\n        # Python 2.7: Everything is in `__main__`.\n        #\n        # Python 3.7: If the bootstrap module is *already imported*, it is the\n        # one we actually want to use (no idea what's in __main__)\n        #\n        # On Python 3.8 bootstrap is also importable, but will be the same file\n        # as __main__ imported under a different name:\n        #\n        #     sys.modules['__main__'].__file__ == sys.modules['bootstrap'].__file__\n        #     sys.modules['__main__'] is not sys.modules['bootstrap']\n        #\n        # Such a setup would then make all monkeypatches useless.\n        if \"bootstrap\" in sys.modules:\n            lambda_bootstrap = sys.modules[\"bootstrap\"]  # type: Any\n        elif \"__main__\" in sys.modules:\n            lambda_bootstrap = sys.modules[\"__main__\"]\n        else:\n            logger.warning(\n                \"Not running in AWS Lambda environment, \"\n                \"AwsLambdaIntegration disabled (could not find bootstrap module)\"\n            )\n            return\n\n        if not hasattr(lambda_bootstrap, \"handle_event_request\"):\n            logger.warning(\n                \"Not running in AWS Lambda environment, \"\n                \"AwsLambdaIntegration disabled (could not find handle_event_request)\"\n            )\n            return\n\n        pre_37 = hasattr(lambda_bootstrap, \"handle_http_request\")  # Python 3.6 or 2.7\n\n        if pre_37:\n            old_handle_event_request = lambda_bootstrap.handle_event_request\n\n            def sentry_handle_event_request(request_handler, *args, **kwargs):\n                # type: (Any, *Any, **Any) -> Any\n                request_handler = _wrap_handler(request_handler)\n                return old_handle_event_request(request_handler, *args, **kwargs)\n\n            lambda_bootstrap.handle_event_request = sentry_handle_event_request\n\n            old_handle_http_request = lambda_bootstrap.handle_http_request\n\n            def sentry_handle_http_request(request_handler, *args, **kwargs):\n                # type: (Any, *Any, **Any) -> Any\n                request_handler = _wrap_handler(request_handler)\n                return old_handle_http_request(request_handler, *args, **kwargs)\n\n            lambda_bootstrap.handle_http_request = sentry_handle_http_request\n\n            # Patch to_json to drain the queue. This should work even when the\n            # SDK is initialized inside of the handler\n\n            old_to_json = lambda_bootstrap.to_json\n\n            def sentry_to_json(*args, **kwargs):\n                # type: (*Any, **Any) -> Any\n                _drain_queue()\n                return old_to_json(*args, **kwargs)\n\n            lambda_bootstrap.to_json = sentry_to_json\n        else:\n            lambda_bootstrap.LambdaRuntimeClient.post_init_error = _wrap_init_error(\n                lambda_bootstrap.LambdaRuntimeClient.post_init_error\n            )\n\n            old_handle_event_request = lambda_bootstrap.handle_event_request\n\n            def sentry_handle_event_request(  # type: ignore\n                lambda_runtime_client, request_handler, *args, **kwargs\n            ):\n                request_handler = _wrap_handler(request_handler)\n                return old_handle_event_request(\n                    lambda_runtime_client, request_handler, *args, **kwargs\n                )\n\n            lambda_bootstrap.handle_event_request = sentry_handle_event_request\n\n            # Patch the runtime client to drain the queue. This should work\n            # even when the SDK is initialized inside of the handler\n\n            def _wrap_post_function(f):\n                # type: (F) -> F\n                def inner(*args, **kwargs):\n                    # type: (*Any, **Any) -> Any\n                    _drain_queue()\n                    return f(*args, **kwargs)\n\n                return inner  # type: ignore\n\n            lambda_bootstrap.LambdaRuntimeClient.post_invocation_result = _wrap_post_function(\n                lambda_bootstrap.LambdaRuntimeClient.post_invocation_result\n            )\n            lambda_bootstrap.LambdaRuntimeClient.post_invocation_error = _wrap_post_function(\n                lambda_bootstrap.LambdaRuntimeClient.post_invocation_error\n            )\n\n\ndef _make_request_event_processor(aws_event, aws_context, configured_timeout):\n    # type: (Any, Any, Any) -> EventProcessor\n    start_time = datetime.now()\n\n    def event_processor(event, hint, start_time=start_time):\n        # type: (Event, Hint, datetime) -> Optional[Event]\n        remaining_time_in_milis = aws_context.get_remaining_time_in_millis()\n        exec_duration = configured_timeout - remaining_time_in_milis\n\n        extra = event.setdefault(\"extra\", {})\n        extra[\"lambda\"] = {\n            \"function_name\": aws_context.function_name,\n            \"function_version\": aws_context.function_version,\n            \"invoked_function_arn\": aws_context.invoked_function_arn,\n            \"aws_request_id\": aws_context.aws_request_id,\n            \"execution_duration_in_millis\": exec_duration,\n            \"remaining_time_in_millis\": remaining_time_in_milis,\n        }\n\n        extra[\"cloudwatch logs\"] = {\n            \"url\": _get_cloudwatch_logs_url(aws_context, start_time),\n            \"log_group\": aws_context.log_group_name,\n            \"log_stream\": aws_context.log_stream_name,\n        }\n\n        request = event.get(\"request\", {})\n\n        if \"httpMethod\" in aws_event:\n            request[\"method\"] = aws_event[\"httpMethod\"]\n\n        request[\"url\"] = _get_url(aws_event, aws_context)\n\n        if \"queryStringParameters\" in aws_event:\n            request[\"query_string\"] = aws_event[\"queryStringParameters\"]\n\n        if \"headers\" in aws_event:\n            request[\"headers\"] = _filter_headers(aws_event[\"headers\"])\n\n        if aws_event.get(\"body\", None):\n            # Unfortunately couldn't find a way to get structured body from AWS\n            # event. Meaning every body is unstructured to us.\n            request[\"data\"] = AnnotatedValue(\"\", {\"rem\": [[\"!raw\", \"x\", 0, 0]]})\n\n        if _should_send_default_pii():\n            user_info = event.setdefault(\"user\", {})\n\n            id = aws_event.get(\"identity\", {}).get(\"userArn\")\n            if id is not None:\n                user_info.setdefault(\"id\", id)\n\n            ip = aws_event.get(\"identity\", {}).get(\"sourceIp\")\n            if ip is not None:\n                user_info.setdefault(\"ip_address\", ip)\n\n        event[\"request\"] = request\n\n        return event\n\n    return event_processor\n\n\ndef _get_url(event, context):\n    # type: (Any, Any) -> str\n    path = event.get(\"path\", None)\n    headers = event.get(\"headers\", {})\n    host = headers.get(\"Host\", None)\n    proto = headers.get(\"X-Forwarded-Proto\", None)\n    if proto and host and path:\n        return \"{}://{}{}\".format(proto, host, path)\n    return \"awslambda:///{}\".format(context.function_name)\n\n\ndef _get_cloudwatch_logs_url(context, start_time):\n    # type: (Any, datetime) -> str\n    \"\"\"\n    Generates a CloudWatchLogs console URL based on the context object\n\n    Arguments:\n        context {Any} -- context from lambda handler\n\n    Returns:\n        str -- AWS Console URL to logs.\n    \"\"\"\n    formatstring = \"%Y-%m-%dT%H:%M:%S\"\n\n    url = (\n        \"https://console.aws.amazon.com/cloudwatch/home?region={region}\"\n        \"#logEventViewer:group={log_group};stream={log_stream}\"\n        \";start={start_time};end={end_time}\"\n    ).format(\n        region=environ.get(\"AWS_REGION\"),\n        log_group=context.log_group_name,\n        log_stream=context.log_stream_name,\n        start_time=(start_time - timedelta(seconds=1)).strftime(formatstring),\n        end_time=(datetime.now() + timedelta(seconds=2)).strftime(formatstring),\n    )\n\n    return url\n", "path": "sentry_sdk/integrations/aws_lambda.py"}]}