Skip to content

feat(transport): Add a timeout #4252

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Apr 10, 2025
13 changes: 13 additions & 0 deletions sentry_sdk/transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ def _parse_rate_limits(header, now=None):
class BaseHttpTransport(Transport):
"""The base HTTP transport."""

TIMEOUT = 30 # seconds

def __init__(self, options):
# type: (Self, Dict[str, Any]) -> None
from sentry_sdk.consts import VERSION
Expand Down Expand Up @@ -621,6 +623,7 @@ def _get_pool_options(self):
options = {
"num_pools": 2 if num_pools is None else int(num_pools),
"cert_reqs": "CERT_REQUIRED",
"timeout": urllib3.Timeout(total=self.TIMEOUT),
}

socket_options = None # type: Optional[List[Tuple[int, int, int | bytes]]]
Expand Down Expand Up @@ -736,6 +739,8 @@ def __init__(self, options):
class Http2Transport(BaseHttpTransport): # type: ignore
"""The HTTP2 transport based on httpcore."""

TIMEOUT = 15

if TYPE_CHECKING:
_pool: Union[
httpcore.SOCKSProxy, httpcore.HTTPProxy, httpcore.ConnectionPool
Expand Down Expand Up @@ -765,6 +770,14 @@ def _request(
self._auth.get_api_url(endpoint_type),
content=body,
headers=headers, # type: ignore
extensions={
"timeout": {
"pool": self.TIMEOUT,
"connect": self.TIMEOUT,
"write": self.TIMEOUT,
"read": self.TIMEOUT,
}
},
)
return response

Expand Down
36 changes: 36 additions & 0 deletions tests/test_transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
from pytest_localserver.http import WSGIServer
from werkzeug.wrappers import Request, Response

try:
import httpcore
except (ImportError, ModuleNotFoundError):
httpcore = None

try:
import gevent
except ImportError:
Expand Down Expand Up @@ -274,6 +279,37 @@ def test_keep_alive_on_by_default(make_client):
assert "socket_options" not in options


def test_default_timeout(make_client):
client = make_client()

options = client.transport._get_pool_options()
assert "timeout" in options
assert options["timeout"].total == client.transport.TIMEOUT


@pytest.mark.skipif(not PY38, reason="HTTP2 libraries are only available in py3.8+")
def test_default_timeout_http2(make_client):
client = make_client(_experiments={"transport_http2": True})

with mock.patch(
"sentry_sdk.transport.httpcore.ConnectionPool.request",
return_value=httpcore.Response(200),
) as request_mock:
sentry_sdk.get_global_scope().set_client(client)
capture_message("hi")
client.flush()

request_mock.assert_called_once()
assert request_mock.call_args.kwargs["extensions"] == {
"timeout": {
"pool": client.transport.TIMEOUT,
"connect": client.transport.TIMEOUT,
"write": client.transport.TIMEOUT,
"read": client.transport.TIMEOUT,
}
}


@pytest.mark.skipif(not PY38, reason="HTTP2 libraries are only available in py3.8+")
def test_http2_with_https_dsn(make_client):
client = make_client(_experiments={"transport_http2": True})
Expand Down
Loading