Skip to content

Commit

Permalink
Merge branch 'master' into ivana/autoenable-httpx
Browse files Browse the repository at this point in the history
  • Loading branch information
sentrivana authored Jun 19, 2023
2 parents 5579a32 + 0792db2 commit 67f25c8
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 25 deletions.
45 changes: 27 additions & 18 deletions sentry_sdk/integrations/celery.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ def _get_humanized_interval(seconds):
interval = int(seconds / divider)
return (interval, unit)

return (1, "minute")
return (int(seconds), "second")


def _get_monitor_config(celery_schedule, app):
Expand All @@ -400,6 +400,12 @@ def _get_monitor_config(celery_schedule, app):
celery_schedule.seconds
)

if schedule_unit == "second":
logger.warning(
"Intervals shorter than one minute are not supported by Sentry Crons."
)
return {}

else:
logger.warning(
"Celery schedule type '%s' not supported by Sentry Crons.",
Expand Down Expand Up @@ -441,24 +447,27 @@ def sentry_apply_entry(*args, **kwargs):

monitor_config = _get_monitor_config(celery_schedule, app)

headers = schedule_entry.options.pop("headers", {})
headers.update(
{
"sentry-monitor-slug": monitor_name,
"sentry-monitor-config": monitor_config,
}
)

check_in_id = capture_checkin(
monitor_slug=monitor_name,
monitor_config=monitor_config,
status=MonitorStatus.IN_PROGRESS,
)
headers.update({"sentry-monitor-check-in-id": check_in_id})
is_supported_schedule = bool(monitor_config)
if is_supported_schedule:
headers = schedule_entry.options.pop("headers", {})
headers.update(
{
"sentry-monitor-slug": monitor_name,
"sentry-monitor-config": monitor_config,
}
)

check_in_id = capture_checkin(
monitor_slug=monitor_name,
monitor_config=monitor_config,
status=MonitorStatus.IN_PROGRESS,
)
headers.update({"sentry-monitor-check-in-id": check_in_id})

# Set the Sentry configuration in the options of the ScheduleEntry.
# Those will be picked up in `apply_async` and added to the headers.
schedule_entry.options["headers"] = headers

# Set the Sentry configuration in the options of the ScheduleEntry.
# Those will be picked up in `apply_async` and added to the headers.
schedule_entry.options["headers"] = headers
return original_apply_entry(*args, **kwargs)

Scheduler.apply_entry = sentry_apply_entry
Expand Down
19 changes: 18 additions & 1 deletion sentry_sdk/transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,24 @@ def _make_pool(
if proxy_headers:
opts["proxy_headers"] = proxy_headers

return urllib3.ProxyManager(proxy, **opts)
if proxy.startswith("socks"):
use_socks_proxy = True
try:
# Check if PySocks depencency is available
from urllib3.contrib.socks import SOCKSProxyManager
except ImportError:
use_socks_proxy = False
logger.warning(
"You have configured a SOCKS proxy (%s) but support for SOCKS proxies is not installed. Disabling proxy support. Please add `PySocks` (or `urllib3` with the `[socks]` extra) to your dependencies.",
proxy,
)

if use_socks_proxy:
return SOCKSProxyManager(proxy, **opts)
else:
return urllib3.PoolManager(**opts)
else:
return urllib3.ProxyManager(proxy, **opts)
else:
return urllib3.PoolManager(**opts)

Expand Down
1 change: 1 addition & 0 deletions test-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ pyrsistent==0.16.0 # TODO(py3): 0.17.0 requires python3, see https://github.com/
executing
asttokens
responses
pysocks
ipdb
34 changes: 28 additions & 6 deletions tests/integrations/celery/test_celery_beat_crons.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,11 @@ def test_get_headers():
@pytest.mark.parametrize(
"seconds, expected_tuple",
[
(0, (1, "minute")),
(0.00001, (1, "minute")),
(1, (1, "minute")),
(0, (0, "second")),
(1, (1, "second")),
(0.00001, (0, "second")),
(59, (59, "second")),
(60, (1, "minute")),
(100, (1, "minute")),
(1000, (16, "minute")),
(10000, (2, "hour")),
Expand Down Expand Up @@ -205,13 +207,12 @@ def test_crons_task_retry():
)


def test_get_monitor_config():
def test_get_monitor_config_crontab():
app = MagicMock()
app.conf = MagicMock()
app.conf.timezone = "Europe/Vienna"

celery_schedule = crontab(day_of_month="3", hour="12", minute="*/10")

monitor_config = _get_monitor_config(celery_schedule, app)
assert monitor_config == {
"schedule": {
Expand All @@ -222,8 +223,23 @@ def test_get_monitor_config():
}
assert "unit" not in monitor_config["schedule"]

celery_schedule = schedule(run_every=3)

def test_get_monitor_config_seconds():
app = MagicMock()
app.conf = MagicMock()
app.conf.timezone = "Europe/Vienna"

celery_schedule = schedule(run_every=3) # seconds
monitor_config = _get_monitor_config(celery_schedule, app)
assert monitor_config == {}


def test_get_monitor_config_minutes():
app = MagicMock()
app.conf = MagicMock()
app.conf.timezone = "Europe/Vienna"

celery_schedule = schedule(run_every=60) # seconds
monitor_config = _get_monitor_config(celery_schedule, app)
assert monitor_config == {
"schedule": {
Expand All @@ -234,6 +250,12 @@ def test_get_monitor_config():
"timezone": "Europe/Vienna",
}


def test_get_monitor_config_unknown():
app = MagicMock()
app.conf = MagicMock()
app.conf.timezone = "Europe/Vienna"

unknown_celery_schedule = MagicMock()
monitor_config = _get_monitor_config(unknown_celery_schedule, app)
assert monitor_config == {}
Expand Down
75 changes: 75 additions & 0 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,14 +252,18 @@ def test_proxy(monkeypatch, testcase):
monkeypatch.setenv("HTTPS_PROXY", testcase["env_https_proxy"])
if testcase.get("env_no_proxy") is not None:
monkeypatch.setenv("NO_PROXY", testcase["env_no_proxy"])

kwargs = {}

if testcase["arg_http_proxy"] is not None:
kwargs["http_proxy"] = testcase["arg_http_proxy"]
if testcase["arg_https_proxy"] is not None:
kwargs["https_proxy"] = testcase["arg_https_proxy"]
if testcase.get("arg_proxy_headers") is not None:
kwargs["proxy_headers"] = testcase["arg_proxy_headers"]

client = Client(testcase["dsn"], **kwargs)

if testcase["expected_proxy_scheme"] is None:
assert client.transport._pool.proxy is None
else:
Expand All @@ -269,6 +273,77 @@ def test_proxy(monkeypatch, testcase):
assert client.transport._pool.proxy_headers == testcase["arg_proxy_headers"]


@pytest.mark.parametrize(
"testcase",
[
{
"dsn": "https://[email protected]/123",
"arg_http_proxy": "http://localhost/123",
"arg_https_proxy": None,
"expected_proxy_class": "<class 'urllib3.poolmanager.ProxyManager'>",
},
{
"dsn": "https://[email protected]/123",
"arg_http_proxy": "socks4a://localhost/123",
"arg_https_proxy": None,
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
},
{
"dsn": "https://[email protected]/123",
"arg_http_proxy": "socks4://localhost/123",
"arg_https_proxy": None,
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
},
{
"dsn": "https://[email protected]/123",
"arg_http_proxy": "socks5h://localhost/123",
"arg_https_proxy": None,
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
},
{
"dsn": "https://[email protected]/123",
"arg_http_proxy": "socks5://localhost/123",
"arg_https_proxy": None,
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
},
{
"dsn": "https://[email protected]/123",
"arg_http_proxy": None,
"arg_https_proxy": "socks4a://localhost/123",
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
},
{
"dsn": "https://[email protected]/123",
"arg_http_proxy": None,
"arg_https_proxy": "socks4://localhost/123",
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
},
{
"dsn": "https://[email protected]/123",
"arg_http_proxy": None,
"arg_https_proxy": "socks5h://localhost/123",
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
},
{
"dsn": "https://[email protected]/123",
"arg_http_proxy": None,
"arg_https_proxy": "socks5://localhost/123",
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
},
],
)
def test_socks_proxy(testcase):
kwargs = {}

if testcase["arg_http_proxy"] is not None:
kwargs["http_proxy"] = testcase["arg_http_proxy"]
if testcase["arg_https_proxy"] is not None:
kwargs["https_proxy"] = testcase["arg_https_proxy"]

client = Client(testcase["dsn"], **kwargs)
assert str(type(client.transport._pool)) == testcase["expected_proxy_class"]


def test_simple_transport(sentry_init):
events = []
sentry_init(transport=events.append)
Expand Down

0 comments on commit 67f25c8

Please sign in to comment.