prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Threading integration breaks OpenCensus' threading integration
  ### How do you use Sentry?
  
  Sentry Saas (sentry.io)
  
  ### Version
  
  1.21.1
  
  ### Steps to Reproduce
  
  1. Enable threading Sentry integration (it seems to be enabled by default)
  2. Enable [threading OpenCensus integration](https://pypi.org/project/opencensus-ext-threading/)
  3. Start a thread
  
  ```python
  import threading
  
  import sentry_sdk.integrations.threading
  import opencensus.trace.config_integration
  
  sentry_sdk.init(integrations=[
      sentry_sdk.integrations.threading.ThreadingIntegration(),
  ])
  
  opencensus.trace.config_integration.trace_integrations(
      integrations=["threading"],
  )
  
  thread = threading.Thread(target=print, args=("foo",))
  thread.start()
  thread.join()
  ```
  
  ### Expected Result
  
  No error, output: `foo`
  
  ### Actual Result
  
  Exceptions raised on every thread's startup
  
  ```python
  Exception in thread Thread-1 (print):
  Traceback (most recent call last):
    File "/usr/lib/python3.10/threading.py", line 1016, in _bootstrap_inner
      self.run()
    File ".venv/lib/python3.10/site-packages/sentry_sdk/integrations/threading.py", line 69, in run
      reraise(*_capture_exception())
    File ".venv/lib/python3.10/site-packages/sentry_sdk/_compat.py", line 60, in reraise
      raise value
    File ".venv/lib/python3.10/site-packages/sentry_sdk/integrations/threading.py", line 67, in run
      return old_run_func(self, *a, **kw)
    File ".venv/lib/python3.10/site-packages/opencensus/ext/threading/trace.py", line 80, in call
      *self._opencensus_context
  AttributeError: 'Thread' object has no attribute '_opencensus_context'
  ```
  
  ### Additional details
  
  * Python: 3.10
  * OpenCensus threading extension: 0.1.2
  
  My suggestion is to use [`functools.update_wrapper`](https://docs.python.org/3/library/functools.html#functools.update_wrapper) (or the convenience decorator [`functools.wraps`](https://docs.python.org/3/library/functools.html#functools.wraps)) to set the name of [`sentry_start`](https://github.com/getsentry/sentry-python/blob/f763061ed9d9e99d85b3e95adc3ed63b623fc4a0/sentry_sdk/integrations/threading.py#L35-54) to `"start"` (and maybe the same for the result of `_wrap_run`, to `"run"`), so it "holds up to basic introspection".
  
  PS: please include 'Additional details' block in issue template
  
  --- 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/threading.py`
  Content:
  ```
  1 from __future__ import absolute_import
  2 
  3 import sys
  4 from threading import Thread, current_thread
  5 
  6 from sentry_sdk import Hub
  7 from sentry_sdk._compat import reraise
  8 from sentry_sdk._types import TYPE_CHECKING
  9 from sentry_sdk.integrations import Integration
  10 from sentry_sdk.utils import event_from_exception, capture_internal_exceptions
  11 
  12 if TYPE_CHECKING:
  13     from typing import Any
  14     from typing import TypeVar
  15     from typing import Callable
  16     from typing import Optional
  17 
  18     from sentry_sdk._types import ExcInfo
  19 
  20     F = TypeVar("F", bound=Callable[..., Any])
  21 
  22 
  23 class ThreadingIntegration(Integration):
  24     identifier = "threading"
  25 
  26     def __init__(self, propagate_hub=False):
  27         # type: (bool) -> None
  28         self.propagate_hub = propagate_hub
  29 
  30     @staticmethod
  31     def setup_once():
  32         # type: () -> None
  33         old_start = Thread.start
  34 
  35         def sentry_start(self, *a, **kw):
  36             # type: (Thread, *Any, **Any) -> Any
  37             hub = Hub.current
  38             integration = hub.get_integration(ThreadingIntegration)
  39             if integration is not None:
  40                 if not integration.propagate_hub:
  41                     hub_ = None
  42                 else:
  43                     hub_ = Hub(hub)
  44                 # Patching instance methods in `start()` creates a reference cycle if
  45                 # done in a naive way. See
  46                 # https://github.com/getsentry/sentry-python/pull/434
  47                 #
  48                 # In threading module, using current_thread API will access current thread instance
  49                 # without holding it to avoid a reference cycle in an easier way.
  50                 with capture_internal_exceptions():
  51                     new_run = _wrap_run(hub_, getattr(self.run, "__func__", self.run))
  52                     self.run = new_run  # type: ignore
  53 
  54             return old_start(self, *a, **kw)
  55 
  56         Thread.start = sentry_start  # type: ignore
  57 
  58 
  59 def _wrap_run(parent_hub, old_run_func):
  60     # type: (Optional[Hub], F) -> F
  61     def run(*a, **kw):
  62         # type: (*Any, **Any) -> Any
  63         hub = parent_hub or Hub.current
  64         with hub:
  65             try:
  66                 self = current_thread()
  67                 return old_run_func(self, *a, **kw)
  68             except Exception:
  69                 reraise(*_capture_exception())
  70 
  71     return run  # type: ignore
  72 
  73 
  74 def _capture_exception():
  75     # type: () -> ExcInfo
  76     hub = Hub.current
  77     exc_info = sys.exc_info()
  78 
  79     if hub.get_integration(ThreadingIntegration) is not None:
  80         # If an integration is there, a client has to be there.
  81         client = hub.client  # type: Any
  82 
  83         event, hint = event_from_exception(
  84             exc_info,
  85             client_options=client.options,
  86             mechanism={"type": "threading", "handled": False},
  87         )
  88         hub.capture_event(event, hint=hint)
  89 
  90     return exc_info
  91
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/sentry_sdk/integrations/threading.py b/sentry_sdk/integrations/threading.py
  --- a/sentry_sdk/integrations/threading.py
  +++ b/sentry_sdk/integrations/threading.py
  @@ -1,6 +1,7 @@
   from __future__ import absolute_import
   
   import sys
  +from functools import wraps
   from threading import Thread, current_thread
   
   from sentry_sdk import Hub
  @@ -32,6 +33,7 @@
           # type: () -> None
           old_start = Thread.start
   
  +        @wraps(old_start)
           def sentry_start(self, *a, **kw):
               # type: (Thread, *Any, **Any) -> Any
               hub = Hub.current
  @@ -58,6 +60,7 @@
   
   def _wrap_run(parent_hub, old_run_func):
       # type: (Optional[Hub], F) -> F
  +    @wraps(old_run_func)
       def run(*a, **kw):
           # type: (*Any, **Any) -> Any
           hub = parent_hub or Hub.current
  
verification_info: {"golden_diff": "diff --git a/sentry_sdk/integrations/threading.py b/sentry_sdk/integrations/threading.py\n--- a/sentry_sdk/integrations/threading.py\n+++ b/sentry_sdk/integrations/threading.py\n@@ -1,6 +1,7 @@\n from __future__ import absolute_import\n \n import sys\n+from functools import wraps\n from threading import Thread, current_thread\n \n from sentry_sdk import Hub\n@@ -32,6 +33,7 @@\n         # type: () -> None\n         old_start = Thread.start\n \n+        @wraps(old_start)\n         def sentry_start(self, *a, **kw):\n             # type: (Thread, *Any, **Any) -> Any\n             hub = Hub.current\n@@ -58,6 +60,7 @@\n \n def _wrap_run(parent_hub, old_run_func):\n     # type: (Optional[Hub], F) -> F\n+    @wraps(old_run_func)\n     def run(*a, **kw):\n         # type: (*Any, **Any) -> Any\n         hub = parent_hub or Hub.current\n", "issue": "Threading integration breaks OpenCensus' threading integration\n### How do you use Sentry?\r\n\r\nSentry Saas (sentry.io)\r\n\r\n### Version\r\n\r\n1.21.1\r\n\r\n### Steps to Reproduce\r\n\r\n1. Enable threading Sentry integration (it seems to be enabled by default)\r\n2. Enable [threading OpenCensus integration](https://pypi.org/project/opencensus-ext-threading/)\r\n3. Start a thread\r\n\r\n```python\r\nimport threading\r\n\r\nimport sentry_sdk.integrations.threading\r\nimport opencensus.trace.config_integration\r\n\r\nsentry_sdk.init(integrations=[\r\n    sentry_sdk.integrations.threading.ThreadingIntegration(),\r\n])\r\n\r\nopencensus.trace.config_integration.trace_integrations(\r\n    integrations=[\"threading\"],\r\n)\r\n\r\nthread = threading.Thread(target=print, args=(\"foo\",))\r\nthread.start()\r\nthread.join()\r\n```\r\n\r\n### Expected Result\r\n\r\nNo error, output: `foo`\r\n\r\n### Actual Result\r\n\r\nExceptions raised on every thread's startup\r\n\r\n```python\r\nException in thread Thread-1 (print):\r\nTraceback (most recent call last):\r\n  File \"/usr/lib/python3.10/threading.py\", line 1016, in _bootstrap_inner\r\n    self.run()\r\n  File \".venv/lib/python3.10/site-packages/sentry_sdk/integrations/threading.py\", line 69, in run\r\n    reraise(*_capture_exception())\r\n  File \".venv/lib/python3.10/site-packages/sentry_sdk/_compat.py\", line 60, in reraise\r\n    raise value\r\n  File \".venv/lib/python3.10/site-packages/sentry_sdk/integrations/threading.py\", line 67, in run\r\n    return old_run_func(self, *a, **kw)\r\n  File \".venv/lib/python3.10/site-packages/opencensus/ext/threading/trace.py\", line 80, in call\r\n    *self._opencensus_context\r\nAttributeError: 'Thread' object has no attribute '_opencensus_context'\r\n```\r\n\r\n### Additional details\r\n\r\n* Python: 3.10\r\n* OpenCensus threading extension: 0.1.2\r\n\r\nMy suggestion is to use [`functools.update_wrapper`](https://docs.python.org/3/library/functools.html#functools.update_wrapper) (or the convenience decorator [`functools.wraps`](https://docs.python.org/3/library/functools.html#functools.wraps)) to set the name of [`sentry_start`](https://github.com/getsentry/sentry-python/blob/f763061ed9d9e99d85b3e95adc3ed63b623fc4a0/sentry_sdk/integrations/threading.py#L35-54) to `\"start\"` (and maybe the same for the result of `_wrap_run`, to `\"run\"`), so it \"holds up to basic introspection\".\r\n\r\nPS: please include 'Additional details' block in issue template\n", "before_files": [{"content": "from __future__ import absolute_import\n\nimport sys\nfrom threading import Thread, current_thread\n\nfrom sentry_sdk import Hub\nfrom sentry_sdk._compat import reraise\nfrom sentry_sdk._types import TYPE_CHECKING\nfrom sentry_sdk.integrations import Integration\nfrom sentry_sdk.utils import event_from_exception, capture_internal_exceptions\n\nif TYPE_CHECKING:\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 ExcInfo\n\n    F = TypeVar(\"F\", bound=Callable[..., Any])\n\n\nclass ThreadingIntegration(Integration):\n    identifier = \"threading\"\n\n    def __init__(self, propagate_hub=False):\n        # type: (bool) -> None\n        self.propagate_hub = propagate_hub\n\n    @staticmethod\n    def setup_once():\n        # type: () -> None\n        old_start = Thread.start\n\n        def sentry_start(self, *a, **kw):\n            # type: (Thread, *Any, **Any) -> Any\n            hub = Hub.current\n            integration = hub.get_integration(ThreadingIntegration)\n            if integration is not None:\n                if not integration.propagate_hub:\n                    hub_ = None\n                else:\n                    hub_ = Hub(hub)\n                # Patching instance methods in `start()` creates a reference cycle if\n                # done in a naive way. See\n                # https://github.com/getsentry/sentry-python/pull/434\n                #\n                # In threading module, using current_thread API will access current thread instance\n                # without holding it to avoid a reference cycle in an easier way.\n                with capture_internal_exceptions():\n                    new_run = _wrap_run(hub_, getattr(self.run, \"__func__\", self.run))\n                    self.run = new_run  # type: ignore\n\n            return old_start(self, *a, **kw)\n\n        Thread.start = sentry_start  # type: ignore\n\n\ndef _wrap_run(parent_hub, old_run_func):\n    # type: (Optional[Hub], F) -> F\n    def run(*a, **kw):\n        # type: (*Any, **Any) -> Any\n        hub = parent_hub or Hub.current\n        with hub:\n            try:\n                self = current_thread()\n                return old_run_func(self, *a, **kw)\n            except Exception:\n                reraise(*_capture_exception())\n\n    return run  # type: ignore\n\n\ndef _capture_exception():\n    # type: () -> ExcInfo\n    hub = Hub.current\n    exc_info = sys.exc_info()\n\n    if hub.get_integration(ThreadingIntegration) is not None:\n        # If an integration is there, a client has to be there.\n        client = hub.client  # type: Any\n\n        event, hint = event_from_exception(\n            exc_info,\n            client_options=client.options,\n            mechanism={\"type\": \"threading\", \"handled\": False},\n        )\n        hub.capture_event(event, hint=hint)\n\n    return exc_info\n", "path": "sentry_sdk/integrations/threading.py"}], "after_files": [{"content": "from __future__ import absolute_import\n\nimport sys\nfrom functools import wraps\nfrom threading import Thread, current_thread\n\nfrom sentry_sdk import Hub\nfrom sentry_sdk._compat import reraise\nfrom sentry_sdk._types import TYPE_CHECKING\nfrom sentry_sdk.integrations import Integration\nfrom sentry_sdk.utils import event_from_exception, capture_internal_exceptions\n\nif TYPE_CHECKING:\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 ExcInfo\n\n    F = TypeVar(\"F\", bound=Callable[..., Any])\n\n\nclass ThreadingIntegration(Integration):\n    identifier = \"threading\"\n\n    def __init__(self, propagate_hub=False):\n        # type: (bool) -> None\n        self.propagate_hub = propagate_hub\n\n    @staticmethod\n    def setup_once():\n        # type: () -> None\n        old_start = Thread.start\n\n        @wraps(old_start)\n        def sentry_start(self, *a, **kw):\n            # type: (Thread, *Any, **Any) -> Any\n            hub = Hub.current\n            integration = hub.get_integration(ThreadingIntegration)\n            if integration is not None:\n                if not integration.propagate_hub:\n                    hub_ = None\n                else:\n                    hub_ = Hub(hub)\n                # Patching instance methods in `start()` creates a reference cycle if\n                # done in a naive way. See\n                # https://github.com/getsentry/sentry-python/pull/434\n                #\n                # In threading module, using current_thread API will access current thread instance\n                # without holding it to avoid a reference cycle in an easier way.\n                with capture_internal_exceptions():\n                    new_run = _wrap_run(hub_, getattr(self.run, \"__func__\", self.run))\n                    self.run = new_run  # type: ignore\n\n            return old_start(self, *a, **kw)\n\n        Thread.start = sentry_start  # type: ignore\n\n\ndef _wrap_run(parent_hub, old_run_func):\n    # type: (Optional[Hub], F) -> F\n    @wraps(old_run_func)\n    def run(*a, **kw):\n        # type: (*Any, **Any) -> Any\n        hub = parent_hub or Hub.current\n        with hub:\n            try:\n                self = current_thread()\n                return old_run_func(self, *a, **kw)\n            except Exception:\n                reraise(*_capture_exception())\n\n    return run  # type: ignore\n\n\ndef _capture_exception():\n    # type: () -> ExcInfo\n    hub = Hub.current\n    exc_info = sys.exc_info()\n\n    if hub.get_integration(ThreadingIntegration) is not None:\n        # If an integration is there, a client has to be there.\n        client = hub.client  # type: Any\n\n        event, hint = event_from_exception(\n            exc_info,\n            client_options=client.options,\n            mechanism={\"type\": \"threading\", \"handled\": False},\n        )\n        hub.capture_event(event, hint=hint)\n\n    return exc_info\n", "path": "sentry_sdk/integrations/threading.py"}]}