Skip to content

Commit 5750739

Browse files
committed
Merge branch 'master' into sentry-sdk-2.0
2 parents 406c68d + 1b0e932 commit 5750739

File tree

9 files changed

+101
-16
lines changed

9 files changed

+101
-16
lines changed

CHANGELOG.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,58 @@
8383
- Passing a function to `sentry_sdk.init`'s `transport` keyword argument has been deprecated. If you wish to provide a custom transport, please pass a `sentry_sdk.transport.Transport` instance or a subclass.
8484
- The parameter `propagate_hub` in `ThreadingIntegration()` was deprecated and renamed to `propagate_scope`.
8585

86+
## 1.41.0
87+
88+
### Various fixes & improvements
89+
90+
- Add recursive scrubbing to `EventScrubber` (#2755) by @Cheapshot003
91+
92+
By default, the `EventScrubber` will not search your events for potential
93+
PII recursively. With this release, you can enable this behavior with:
94+
95+
```python
96+
import sentry_sdk
97+
from sentry_sdk.scrubber import EventScrubber
98+
99+
sentry_sdk.init(
100+
# ...your usual settings...
101+
event_scrubber=EventScrubber(recursive=True),
102+
)
103+
```
104+
105+
- Expose `socket_options` (#2786) by @sentrivana
106+
107+
If the SDK is experiencing connection issues (connection resets, server
108+
closing connection without response, etc.) while sending events to Sentry,
109+
tweaking the default `urllib3` socket options to the following can help:
110+
111+
```python
112+
import socket
113+
from urllib3.connection import HTTPConnection
114+
import sentry_sdk
115+
116+
sentry_sdk.init(
117+
# ...your usual settings...
118+
socket_options=HTTPConnection.default_socket_options + [
119+
(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1),
120+
# note: skip the following line if you're on MacOS since TCP_KEEPIDLE doesn't exist there
121+
(socket.SOL_TCP, socket.TCP_KEEPIDLE, 45),
122+
(socket.SOL_TCP, socket.TCP_KEEPINTVL, 10),
123+
(socket.SOL_TCP, socket.TCP_KEEPCNT, 6),
124+
],
125+
)
126+
```
127+
128+
- Allow to configure merge target for releases (#2777) by @sentrivana
129+
- Allow empty character in metric tags values (#2775) by @viglia
130+
- Replace invalid tag values with an empty string instead of _ (#2773) by @markushi
131+
- Add documentation comment to `scrub_list` (#2769) by @szokeasaurusrex
132+
- Fixed regex to parse version in lambda package file (#2767) by @antonpirker
133+
- xfail broken AWS Lambda tests for now (#2794) by @sentrivana
134+
- Removed print statements because it messes with the tests (#2789) by @antonpirker
135+
- Bump `types-protobuf` from 4.24.0.20240129 to 4.24.0.20240302 (#2782) by @dependabot
136+
- Bump `checkouts/data-schemas` from `eb941c2` to `ed078ed` (#2781) by @dependabot
137+
86138
## 1.40.6
87139

88140
### Various fixes & improvements

linter-requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ mypy
22
black
33
flake8==5.0.4 # flake8 depends on pyflakes>=3.0.0 and this dropped support for Python 2 "# type:" comments
44
types-certifi
5-
types-protobuf==4.24.0.20240129 # newer raises an error on mypy sentry_sdk
5+
types-protobuf==4.24.0.20240302 # newer raises an error on mypy sentry_sdk
66
types-redis
77
types-setuptools
88
pymongo # There is no separate types module.

sentry_sdk/client.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,12 @@ def _get_options(*args, **kwargs):
124124
if rv["event_scrubber"] is None:
125125
rv["event_scrubber"] = EventScrubber()
126126

127+
if rv["socket_options"] and not isinstance(rv["socket_options"], list):
128+
logger.warning(
129+
"Ignoring socket_options because of unexpected format. See urllib3.HTTPConnection.socket_options for the expected format."
130+
)
131+
rv["socket_options"] = None
132+
127133
return rv
128134

129135

sentry_sdk/consts.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class EndpointType(Enum):
2727
from typing import Dict
2828
from typing import Any
2929
from typing import Sequence
30+
from typing import Tuple
3031
from typing_extensions import TypedDict
3132

3233
from sentry_sdk.integrations import Integration
@@ -270,6 +271,7 @@ def __init__(
270271
https_proxy=None, # type: Optional[str]
271272
ignore_errors=[], # type: Sequence[Union[type, str]] # noqa: B006
272273
max_request_body_size="medium", # type: str
274+
socket_options=None, # type: Optional[List[Tuple[int, int, int | bytes]]]
273275
before_send=None, # type: Optional[EventProcessor]
274276
before_breadcrumb=None, # type: Optional[BreadcrumbProcessor]
275277
debug=None, # type: Optional[bool]

sentry_sdk/transport.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@
77
import time
88
from datetime import datetime, timedelta, timezone
99
from collections import defaultdict
10+
import certifi
11+
import urllib3
1012
from urllib.request import getproxies
1113

1214
from sentry_sdk.consts import EndpointType
1315
from sentry_sdk.utils import Dsn, logger, capture_internal_exceptions
1416
from sentry_sdk.worker import BackgroundWorker
1517
from sentry_sdk.envelope import Envelope, Item, PayloadRef
18+
1619
from sentry_sdk._types import TYPE_CHECKING
1720

1821
if TYPE_CHECKING:
@@ -417,12 +420,17 @@ def _send_envelope(
417420

418421
def _get_pool_options(self, ca_certs):
419422
# type: (Optional[Any]) -> Dict[str, Any]
420-
return {
423+
options = {
421424
"num_pools": self._num_pools,
422425
"cert_reqs": "CERT_REQUIRED",
423426
"ca_certs": ca_certs or certifi.where(),
424427
}
425428

429+
if self.options["socket_options"]:
430+
options["socket_options"] = self.options["socket_options"]
431+
432+
return options
433+
426434
def _in_no_proxy(self, parsed_dsn):
427435
# type: (Dsn) -> bool
428436
no_proxy = getproxies().get("no")

tests/integrations/aws_lambda/client.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ def run_lambda_function(
240240
FunctionName=full_fn_name,
241241
)
242242
print(
243-
f"Lambda function {full_fn_name} in AWS already existing, taking it (and do not create a local one)"
243+
"Lambda function in AWS already existing, taking it (and do not create a local one)"
244244
)
245245
except client.exceptions.ResourceNotFoundException:
246246
function_exists_in_aws = False
@@ -251,14 +251,9 @@ def run_lambda_function(
251251
dir_already_existing = os.path.isdir(base_dir)
252252

253253
if dir_already_existing:
254-
print(
255-
f"Local Lambda function directory ({base_dir}) already exists, skipping creation"
256-
)
254+
print("Local Lambda function directory already exists, skipping creation")
257255

258256
if not dir_already_existing:
259-
print(
260-
f"Creating Lambda function package ({full_fn_name}) locally in directory {base_dir}"
261-
)
262257
os.mkdir(base_dir)
263258
_create_lambda_package(
264259
base_dir, code, initial_handler, layer, syntax_check, subprocess_kwargs
@@ -321,10 +316,9 @@ def clean_up():
321316

322317
waiter = client.get_waiter("function_active_v2")
323318
waiter.wait(FunctionName=full_fn_name)
324-
print(f"Created Lambda function in AWS: {full_fn_name}")
325319
except client.exceptions.ResourceConflictException:
326320
print(
327-
f"Lambda function ({full_fn_name}) already existing in AWS, this is fine, we will just invoke it."
321+
"Lambda function already exists, this is fine, we will just invoke it."
328322
)
329323

330324
response = client.invoke(

tests/integrations/aws_lambda/test_aws.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,9 @@ def test_handler(event, context):
650650
assert response["Payload"]["AssertionError raised"] is False
651651

652652

653+
@pytest.mark.xfail(
654+
reason="The limited log output we depend on is being clogged by a new warning"
655+
)
653656
def test_serverless_no_code_instrumentation(run_lambda_function):
654657
"""
655658
Test that ensures that just by adding a lambda layer containing the
@@ -694,6 +697,9 @@ def test_handler(event, context):
694697
assert "sentry_handler" in response["LogResult"][3].decode("utf-8")
695698

696699

700+
@pytest.mark.xfail(
701+
reason="The limited log output we depend on is being clogged by a new warning"
702+
)
697703
def test_error_has_new_trace_context_performance_enabled(run_lambda_function):
698704
envelope_items, _ = run_lambda_function(
699705
LAMBDA_PRELUDE
@@ -756,6 +762,9 @@ def test_handler(event, context):
756762
)
757763

758764

765+
@pytest.mark.xfail(
766+
reason="The limited log output we depend on is being clogged by a new warning"
767+
)
759768
def test_error_has_existing_trace_context_performance_enabled(run_lambda_function):
760769
trace_id = "471a43a4192642f0b136d5159a501701"
761770
parent_span_id = "6e8f22c393e68f19"

tests/test_transport.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import pickle
33
import gzip
44
import io
5+
import socket
56
from collections import namedtuple
67
from datetime import datetime, timedelta, timezone
78
from unittest import mock
@@ -150,6 +151,19 @@ def test_transport_num_pools(make_client, num_pools, expected_num_pools):
150151
assert options["num_pools"] == expected_num_pools
151152

152153

154+
def test_socket_options(make_client):
155+
socket_options = [
156+
(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1),
157+
(socket.SOL_TCP, socket.TCP_KEEPINTVL, 10),
158+
(socket.SOL_TCP, socket.TCP_KEEPCNT, 6),
159+
]
160+
161+
client = make_client(socket_options=socket_options)
162+
163+
options = client.transport._get_pool_options([])
164+
assert options["socket_options"] == socket_options
165+
166+
153167
def test_transport_infinite_loop(capturing_server, request, make_client):
154168
client = make_client(
155169
debug=True,
@@ -221,7 +235,7 @@ def test_parse_rate_limits(input, expected):
221235
assert dict(_parse_rate_limits(input, now=NOW)) == expected
222236

223237

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

@@ -243,7 +257,7 @@ def test_simple_rate_limits(capturing_server, capsys, caplog, make_client):
243257

244258
@pytest.mark.parametrize("response_code", [200, 429])
245259
def test_data_category_limits(
246-
capturing_server, capsys, caplog, response_code, make_client, monkeypatch
260+
capturing_server, response_code, make_client, monkeypatch
247261
):
248262
client = make_client(send_client_reports=False)
249263

@@ -290,7 +304,7 @@ def record_lost_event(reason, data_category=None, item=None):
290304

291305
@pytest.mark.parametrize("response_code", [200, 429])
292306
def test_data_category_limits_reporting(
293-
capturing_server, capsys, caplog, response_code, make_client, monkeypatch
307+
capturing_server, response_code, make_client, monkeypatch
294308
):
295309
client = make_client(send_client_reports=True)
296310

@@ -374,7 +388,7 @@ def intercepting_fetch(*args, **kwargs):
374388

375389
@pytest.mark.parametrize("response_code", [200, 429])
376390
def test_complex_limits_without_data_category(
377-
capturing_server, capsys, caplog, response_code, make_client
391+
capturing_server, response_code, make_client
378392
):
379393
client = make_client()
380394
capturing_server.respond_with(

0 commit comments

Comments
 (0)