From 082d56cd65d8dc70d60dcae9e41d06e0df9c2d1e Mon Sep 17 00:00:00 2001 From: svartalf Date: Wed, 24 Sep 2025 11:10:28 +0200 Subject: [PATCH 1/2] fix(Ray): Retain the original function name when patching Ray tasks Without "@functools.wraps" added, Ray exposes Prometheus metrics with all tasks named "new_func" --- sentry_sdk/integrations/ray.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/sentry_sdk/integrations/ray.py b/sentry_sdk/integrations/ray.py index 8d6cdc1201..a2ecd150df 100644 --- a/sentry_sdk/integrations/ray.py +++ b/sentry_sdk/integrations/ray.py @@ -1,4 +1,5 @@ import inspect +import functools import sys import sentry_sdk @@ -17,7 +18,6 @@ import ray # type: ignore[import-not-found] except ImportError: raise DidNotEnable("Ray not installed.") -import functools from typing import TYPE_CHECKING @@ -54,6 +54,7 @@ def new_remote(f=None, *args, **kwargs): def wrapper(user_f): # type: (Callable[..., Any]) -> Any + @functools.wraps(user_f) def new_func(*f_args, _tracing=None, **f_kwargs): # type: (Any, Optional[dict[str, Any]], Any) -> Any _check_sentry_initialized() @@ -78,6 +79,19 @@ def new_func(*f_args, _tracing=None, **f_kwargs): return result + # Patching new_func signature to add the _tracing parameter to it + # Ray later inspects the signature and finds the unexpected parameter otherwise + signature = inspect.signature(new_func) + params = list(signature.parameters.values()) + params.append( + inspect.Parameter( + "_tracing", + kind=inspect.Parameter.KEYWORD_ONLY, + default=None, + ) + ) + new_func.__signature__ = signature.replace(parameters=params) + if f: rv = old_remote(new_func) else: From 93ce3100891564a9ed854fccadcfa3d4d147b081 Mon Sep 17 00:00:00 2001 From: svartalf Date: Fri, 10 Oct 2025 11:44:31 +0200 Subject: [PATCH 2/2] Review fixes --- sentry_sdk/integrations/ray.py | 14 ++++++++------ tests/integrations/ray/test_ray.py | 3 +++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/sentry_sdk/integrations/ray.py b/sentry_sdk/integrations/ray.py index a2ecd150df..08e78b7585 100644 --- a/sentry_sdk/integrations/ray.py +++ b/sentry_sdk/integrations/ray.py @@ -55,12 +55,12 @@ def new_remote(f=None, *args, **kwargs): def wrapper(user_f): # type: (Callable[..., Any]) -> Any @functools.wraps(user_f) - def new_func(*f_args, _tracing=None, **f_kwargs): + def new_func(*f_args, _sentry_tracing=None, **f_kwargs): # type: (Any, Optional[dict[str, Any]], Any) -> Any _check_sentry_initialized() transaction = sentry_sdk.continue_trace( - _tracing or {}, + _sentry_tracing or {}, op=OP.QUEUE_TASK_RAY, name=qualname_from_function(user_f), origin=RayIntegration.origin, @@ -79,18 +79,18 @@ def new_func(*f_args, _tracing=None, **f_kwargs): return result - # Patching new_func signature to add the _tracing parameter to it + # Patching new_func signature to add the _sentry_tracing parameter to it # Ray later inspects the signature and finds the unexpected parameter otherwise signature = inspect.signature(new_func) params = list(signature.parameters.values()) params.append( inspect.Parameter( - "_tracing", + "_sentry_tracing", kind=inspect.Parameter.KEYWORD_ONLY, default=None, ) ) - new_func.__signature__ = signature.replace(parameters=params) + new_func.__signature__ = signature.replace(parameters=params) # type: ignore[attr-defined] if f: rv = old_remote(new_func) @@ -113,7 +113,9 @@ def _remote_method_with_header_propagation(*args, **kwargs): for k, v in sentry_sdk.get_current_scope().iter_trace_propagation_headers() } try: - result = old_remote_method(*args, **kwargs, _tracing=tracing) + result = old_remote_method( + *args, **kwargs, _sentry_tracing=tracing + ) span.set_status(SPANSTATUS.OK) except Exception: span.set_status(SPANSTATUS.INTERNAL_ERROR) diff --git a/tests/integrations/ray/test_ray.py b/tests/integrations/ray/test_ray.py index f4e67df038..6aaced391e 100644 --- a/tests/integrations/ray/test_ray.py +++ b/tests/integrations/ray/test_ray.py @@ -100,6 +100,9 @@ def example_task(): else: example_task = ray.remote(example_task) + # Function name shouldn't be overwritten by Sentry wrapper + assert example_task._function_name == "tests.integrations.ray.test_ray.example_task" + with sentry_sdk.start_transaction(op="task", name="ray test transaction"): worker_envelopes = ray.get(example_task.remote())