Skip to content

Commit

Permalink
feat(transport): Expose socket_options (#2786)
Browse files Browse the repository at this point in the history
  • Loading branch information
sentrivana committed Mar 5, 2024
1 parent 0901953 commit c5785fb
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 13 deletions.
6 changes: 6 additions & 0 deletions sentry_sdk/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,12 @@ def _get_options(*args, **kwargs):
if rv["event_scrubber"] is None:
rv["event_scrubber"] = EventScrubber()

if rv["socket_options"] and not isinstance(rv["socket_options"], list):
logger.warning(
"Ignoring socket_options because of unexpected format. See urllib3.HTTPConnection.socket_options for the expected format."
)
rv["socket_options"] = None

return rv


Expand Down
2 changes: 2 additions & 0 deletions sentry_sdk/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from typing import Dict
from typing import Any
from typing import Sequence
from typing import Tuple
from typing_extensions import TypedDict

from sentry_sdk.integrations import Integration
Expand Down Expand Up @@ -260,6 +261,7 @@ def __init__(
https_proxy=None, # type: Optional[str]
ignore_errors=[], # type: Sequence[Union[type, str]] # noqa: B006
max_request_body_size="medium", # type: str
socket_options=None, # type: Optional[List[Tuple[int, int, int | bytes]]]
before_send=None, # type: Optional[EventProcessor]
before_breadcrumb=None, # type: Optional[BreadcrumbProcessor]
debug=None, # type: Optional[bool]
Expand Down
14 changes: 9 additions & 5 deletions sentry_sdk/transport.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
from __future__ import print_function

import io
import urllib3
import certifi
import gzip
import time

from datetime import timedelta
from collections import defaultdict

import urllib3
import certifi

from sentry_sdk.utils import Dsn, logger, capture_internal_exceptions, json_dumps
from sentry_sdk.worker import BackgroundWorker
from sentry_sdk.envelope import Envelope, Item, PayloadRef

from sentry_sdk._compat import datetime_utcnow
from sentry_sdk._types import TYPE_CHECKING

Expand Down Expand Up @@ -441,12 +440,17 @@ def _send_envelope(

def _get_pool_options(self, ca_certs):
# type: (Optional[Any]) -> Dict[str, Any]
return {
options = {
"num_pools": self._num_pools,
"cert_reqs": "CERT_REQUIRED",
"ca_certs": ca_certs or certifi.where(),
}

if self.options["socket_options"]:
options["socket_options"] = self.options["socket_options"]

return options

def _in_no_proxy(self, parsed_dsn):
# type: (Dsn) -> bool
no_proxy = getproxies().get("no")
Expand Down
28 changes: 20 additions & 8 deletions tests/test_transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@
import pickle
import gzip
import io

import socket
from collections import namedtuple
from datetime import datetime, timedelta

import pytest
from collections import namedtuple
from werkzeug.wrappers import Request, Response

from pytest_localserver.http import WSGIServer
from werkzeug.wrappers import Request, Response

from sentry_sdk import Hub, Client, add_breadcrumb, capture_message, Scope
from sentry_sdk._compat import datetime_utcnow
Expand Down Expand Up @@ -155,6 +154,19 @@ def test_transport_num_pools(make_client, num_pools, expected_num_pools):
assert options["num_pools"] == expected_num_pools


def test_socket_options(make_client):
socket_options = [
(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1),
(socket.SOL_TCP, socket.TCP_KEEPINTVL, 10),
(socket.SOL_TCP, socket.TCP_KEEPCNT, 6),
]

client = make_client(socket_options=socket_options)

options = client.transport._get_pool_options([])
assert options["socket_options"] == socket_options


def test_transport_infinite_loop(capturing_server, request, make_client):
client = make_client(
debug=True,
Expand Down Expand Up @@ -219,7 +231,7 @@ def test_parse_rate_limits(input, expected):
assert dict(_parse_rate_limits(input, now=NOW)) == expected


def test_simple_rate_limits(capturing_server, capsys, caplog, make_client):
def test_simple_rate_limits(capturing_server, make_client):
client = make_client()
capturing_server.respond_with(code=429, headers={"Retry-After": "4"})

Expand All @@ -241,7 +253,7 @@ def test_simple_rate_limits(capturing_server, capsys, caplog, make_client):

@pytest.mark.parametrize("response_code", [200, 429])
def test_data_category_limits(
capturing_server, capsys, caplog, response_code, make_client, monkeypatch
capturing_server, response_code, make_client, monkeypatch
):
client = make_client(send_client_reports=False)

Expand Down Expand Up @@ -288,7 +300,7 @@ def record_lost_event(reason, data_category=None, item=None):

@pytest.mark.parametrize("response_code", [200, 429])
def test_data_category_limits_reporting(
capturing_server, capsys, caplog, response_code, make_client, monkeypatch
capturing_server, response_code, make_client, monkeypatch
):
client = make_client(send_client_reports=True)

Expand Down Expand Up @@ -371,7 +383,7 @@ def intercepting_fetch(*args, **kwargs):

@pytest.mark.parametrize("response_code", [200, 429])
def test_complex_limits_without_data_category(
capturing_server, capsys, caplog, response_code, make_client
capturing_server, response_code, make_client
):
client = make_client()
capturing_server.respond_with(
Expand Down

0 comments on commit c5785fb

Please sign in to comment.