Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test-integrations-tasks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.7","3.10","3.11","3.12","3.13"]
python-version: ["3.7","3.12","3.13"]
# python3.6 reached EOL and is no longer being supported on
# new versions of hosted runners on Github Actions
# ubuntu-20.04 is the last version that supported python3.6
Expand Down
5 changes: 5 additions & 0 deletions scripts/populate_tox/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,11 @@
"py3.8": ["taskgroup==0.0.0a4"],
},
},
"ray": {
"package": "ray",
"python": ">=3.9",
"num_versions": 2,
},
"redis_py_cluster_legacy": {
"package": "redis-py-cluster",
},
Expand Down
1 change: 0 additions & 1 deletion scripts/populate_tox/populate_tox.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@
# of these from the IGNORE list
"gcp",
"httpx",
"ray",
"redis",
"requests",
"rq",
Expand Down
8 changes: 0 additions & 8 deletions scripts/populate_tox/tox.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,6 @@ envlist =
# OpenTelemetry Experimental (POTel)
{py3.8,py3.9,py3.10,py3.11,py3.12,py3.13}-potel

# Ray
{py3.10,py3.11}-ray-v{2.34}
{py3.10,py3.11}-ray-latest

# Redis
{py3.6,py3.8}-redis-v{3}
{py3.7,py3.8,py3.11}-redis-v{4}
Expand Down Expand Up @@ -168,10 +164,6 @@ deps =
# OpenTelemetry Experimental (POTel)
potel: -e .[opentelemetry-experimental]

# Ray
ray-v2.34: ray~=2.34.0
ray-latest: ray

# Redis
redis: fakeredis!=1.7.4
redis: pytest<8.0.0
Expand Down
154 changes: 92 additions & 62 deletions tests/integrations/ray/test_ray.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import json
import os
import pytest
import shutil
import uuid

import ray

Expand All @@ -10,6 +12,12 @@
from tests.conftest import TestTransport


@pytest.fixture(autouse=True)
def shutdown_ray(tmpdir):
yield
ray.shutdown()


class RayTestTransport(TestTransport):
def __init__(self):
self.envelopes = []
Expand All @@ -20,9 +28,6 @@ def capture_envelope(self, envelope: Envelope) -> None:


class RayLoggingTransport(TestTransport):
def __init__(self):
super().__init__()

def capture_envelope(self, envelope: Envelope) -> None:
print(envelope.serialize().decode("utf-8", "replace"))

Expand All @@ -39,13 +44,24 @@ def setup_sentry(transport=None):
)


def read_error_from_log(job_id):
log_dir = "/tmp/ray/session_latest/logs/"
def read_error_from_log(job_id, ray_temp_dir):
# Find the actual session directory that Ray created
session_dirs = [d for d in os.listdir(ray_temp_dir) if d.startswith("session_")]
if not session_dirs:
raise FileNotFoundError(f"No session directory found in {ray_temp_dir}")

session_dir = os.path.join(ray_temp_dir, session_dirs[0])
log_dir = os.path.join(session_dir, "logs")

if not os.path.exists(log_dir):
raise FileNotFoundError(f"No logs directory found at {log_dir}")

log_file = [
f
for f in os.listdir(log_dir)
if "worker" in f and job_id in f and f.endswith(".out")
][0]

with open(os.path.join(log_dir, log_file), "r") as file:
lines = file.readlines()

Expand All @@ -58,7 +74,6 @@ def read_error_from_log(job_id):
return error


@pytest.mark.forked
@pytest.mark.parametrize(
"task_options", [{}, {"num_cpus": 0, "memory": 1024 * 1024 * 10}]
)
Expand Down Expand Up @@ -124,40 +139,47 @@ def example_task():
)


@pytest.mark.forked
def test_errors_in_ray_tasks():
setup_sentry_with_logging_transport()

ray.init(
runtime_env={
"worker_process_setup_hook": setup_sentry_with_logging_transport,
"working_dir": "./",
}
)
ray_temp_dir = os.path.join("/tmp", f"ray_test_{uuid.uuid4().hex[:8]}")
os.makedirs(ray_temp_dir, exist_ok=True)

# Setup ray task
@ray.remote
def example_task():
1 / 0
try:
ray.init(
runtime_env={
"worker_process_setup_hook": setup_sentry_with_logging_transport,
"working_dir": "./",
},
_temp_dir=ray_temp_dir,
)

with sentry_sdk.start_transaction(op="task", name="ray test transaction"):
with pytest.raises(ZeroDivisionError):
future = example_task.remote()
ray.get(future)
# Setup ray task
@ray.remote
def example_task():
1 / 0

job_id = future.job_id().hex()
error = read_error_from_log(job_id)
with sentry_sdk.start_transaction(op="task", name="ray test transaction"):
with pytest.raises(ZeroDivisionError):
future = example_task.remote()
ray.get(future)

assert error["level"] == "error"
assert (
error["transaction"]
== "tests.integrations.ray.test_ray.test_errors_in_ray_tasks.<locals>.example_task"
)
assert error["exception"]["values"][0]["mechanism"]["type"] == "ray"
assert not error["exception"]["values"][0]["mechanism"]["handled"]
job_id = future.job_id().hex()
error = read_error_from_log(job_id, ray_temp_dir)

assert error["level"] == "error"
assert (
error["transaction"]
== "tests.integrations.ray.test_ray.test_errors_in_ray_tasks.<locals>.example_task"
)
assert error["exception"]["values"][0]["mechanism"]["type"] == "ray"
assert not error["exception"]["values"][0]["mechanism"]["handled"]

finally:
if os.path.exists(ray_temp_dir):
shutil.rmtree(ray_temp_dir, ignore_errors=True)


@pytest.mark.forked
def test_tracing_in_ray_actors():
setup_sentry()

Expand Down Expand Up @@ -194,37 +216,45 @@ def increment(self):
assert worker_envelopes == []


@pytest.mark.forked
def test_errors_in_ray_actors():
setup_sentry_with_logging_transport()

ray.init(
runtime_env={
"worker_process_setup_hook": setup_sentry_with_logging_transport,
"working_dir": "./",
}
)

# Setup ray actor
@ray.remote
class Counter:
def __init__(self):
self.n = 0

def increment(self):
with sentry_sdk.start_span(op="task", name="example actor execution"):
1 / 0

return sentry_sdk.get_client().transport.envelopes

with sentry_sdk.start_transaction(op="task", name="ray test transaction"):
with pytest.raises(ZeroDivisionError):
counter = Counter.remote()
future = counter.increment.remote()
ray.get(future)

job_id = future.job_id().hex()
error = read_error_from_log(job_id)

# We do not capture errors in ray actors yet
assert error is None
ray_temp_dir = os.path.join("/tmp", f"ray_test_{uuid.uuid4().hex[:8]}")
os.makedirs(ray_temp_dir, exist_ok=True)

try:
ray.init(
runtime_env={
"worker_process_setup_hook": setup_sentry_with_logging_transport,
"working_dir": "./",
},
_temp_dir=ray_temp_dir,
)

# Setup ray actor
@ray.remote
class Counter:
def __init__(self):
self.n = 0

def increment(self):
with sentry_sdk.start_span(op="task", name="example actor execution"):
1 / 0

return sentry_sdk.get_client().transport.envelopes

with sentry_sdk.start_transaction(op="task", name="ray test transaction"):
with pytest.raises(ZeroDivisionError):
counter = Counter.remote()
future = counter.increment.remote()
ray.get(future)

job_id = future.job_id().hex()
error = read_error_from_log(job_id, ray_temp_dir)

# We do not capture errors in ray actors yet
assert error is None

finally:
if os.path.exists(ray_temp_dir):
shutil.rmtree(ray_temp_dir, ignore_errors=True)
16 changes: 7 additions & 9 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# The file (and all resulting CI YAMLs) then need to be regenerated via
# "scripts/generate-test-files.sh".
#
# Last generated: 2025-09-18T08:05:49.500134+00:00
# Last generated: 2025-09-18T10:26:22.484602+00:00

[tox]
requires =
Expand Down Expand Up @@ -61,10 +61,6 @@ envlist =
# OpenTelemetry Experimental (POTel)
{py3.8,py3.9,py3.10,py3.11,py3.12,py3.13}-potel

# Ray
{py3.10,py3.11}-ray-v{2.34}
{py3.10,py3.11}-ray-latest

# Redis
{py3.6,py3.8}-redis-v{3}
{py3.7,py3.8,py3.11}-redis-v{4}
Expand Down Expand Up @@ -233,6 +229,9 @@ envlist =
{py3.6,py3.7}-huey-v2.3.2
{py3.6,py3.11,py3.12}-huey-v2.5.3

{py3.9,py3.10}-ray-v2.7.2
{py3.9,py3.12,py3.13}-ray-v2.49.1

{py3.8,py3.9}-spark-v3.0.3
{py3.8,py3.10,py3.11}-spark-v3.5.6
{py3.9,py3.12,py3.13}-spark-v4.0.1
Expand Down Expand Up @@ -396,10 +395,6 @@ deps =
# OpenTelemetry Experimental (POTel)
potel: -e .[opentelemetry-experimental]

# Ray
ray-v2.34: ray~=2.34.0
ray-latest: ray

# Redis
redis: fakeredis!=1.7.4
redis: pytest<8.0.0
Expand Down Expand Up @@ -631,6 +626,9 @@ deps =
huey-v2.3.2: huey==2.3.2
huey-v2.5.3: huey==2.5.3

ray-v2.7.2: ray==2.7.2
ray-v2.49.1: ray==2.49.1

spark-v3.0.3: pyspark==3.0.3
spark-v3.5.6: pyspark==3.5.6
spark-v4.0.1: pyspark==4.0.1
Expand Down