Skip to content

Commit 2e05fdf

Browse files
committed
Merge branch 'potel-base' into potel-base-run-all-tests
2 parents 2bef511 + db1cfe6 commit 2e05fdf

File tree

16 files changed

+271
-76
lines changed

16 files changed

+271
-76
lines changed

.github/workflows/test-integrations-dbs.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ jobs:
5353
with:
5454
python-version: ${{ matrix.python-version }}
5555
allow-prereleases: true
56-
- uses: getsentry/action-clickhouse-in-ci@v1
56+
- uses: getsentry/action-clickhouse-in-ci@v1.1
5757
- name: Setup Test Env
5858
run: |
5959
pip install "coverage[toml]" tox
@@ -144,7 +144,7 @@ jobs:
144144
with:
145145
python-version: ${{ matrix.python-version }}
146146
allow-prereleases: true
147-
- uses: getsentry/action-clickhouse-in-ci@v1
147+
- uses: getsentry/action-clickhouse-in-ci@v1.1
148148
- name: Setup Test Env
149149
run: |
150150
pip install "coverage[toml]" tox

CHANGELOG.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,31 @@
11
# Changelog
22

3+
## 2.19.0
4+
5+
### Various fixes & improvements
6+
7+
- New: introduce `rust_tracing` integration. See https://docs.sentry.io/platforms/python/integrations/rust_tracing/ (#3717) by @matt-codecov
8+
- Auto enable Litestar integration (#3540) by @provinzkraut
9+
- Deprecate `sentry_sdk.init` context manager (#3729) by @szokeasaurusrex
10+
- feat(spotlight): Send PII to Spotlight when no DSN is set (#3804) by @BYK
11+
- feat(spotlight): Add info logs when Sentry is enabled (#3735) by @BYK
12+
- feat(spotlight): Inject Spotlight button on Django (#3751) by @BYK
13+
- feat(spotlight): Auto enable cache_spans for Spotlight on DEBUG (#3791) by @BYK
14+
- fix(logging): Handle parameter `stack_info` for the `LoggingIntegration` (#3745) by @gmcrocetti
15+
- fix(pure-eval): Make sentry-sdk[pure-eval] installable with pip==24.0 (#3757) by @sentrivana
16+
- fix(rust_tracing): include_tracing_fields arg to control unvetted data in rust_tracing integration (#3780) by @matt-codecov
17+
- fix(aws) Fix aws lambda tests (by reducing event size) (#3770) by @antonpirker
18+
- fix(arq): fix integration with Worker settings as a dict (#3742) by @saber-solooki
19+
- fix(httpx): Prevent Sentry baggage duplication (#3728) by @szokeasaurusrex
20+
- fix(falcon): Don't exhaust request body stream (#3768) by @szokeasaurusrex
21+
- fix(integrations): Check `retries_left` before capturing exception (#3803) by @malkovro
22+
- fix(openai): Use name instead of description (#3807) by @sourceful-rob
23+
- test(gcp): Only run GCP tests when they should (#3721) by @szokeasaurusrex
24+
- chore: Shorten CI workflow names (#3805) by @sentrivana
25+
- chore: Test with pyspark prerelease (#3760) by @sentrivana
26+
- build(deps): bump codecov/codecov-action from 4.6.0 to 5.0.2 (#3792) by @dependabot
27+
- build(deps): bump actions/checkout from 4.2.1 to 4.2.2 (#3691) by @dependabot
28+
329
## 2.18.0
430

531
### Various fixes & improvements

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
copyright = "2019-{}, Sentry Team and Contributors".format(datetime.now().year)
3232
author = "Sentry Team and Contributors"
3333

34-
release = "2.18.0"
34+
release = "2.19.0"
3535
version = ".".join(release.split(".")[:2]) # The short X.Y version.
3636

3737

scripts/split-tox-gh-actions/templates/test_group.jinja

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
python-version: {% raw %}${{ matrix.python-version }}{% endraw %}
4848
allow-prereleases: true
4949
{% if needs_clickhouse %}
50-
- uses: getsentry/action-clickhouse-in-ci@v1
50+
- uses: getsentry/action-clickhouse-in-ci@v1.1
5151
{% endif %}
5252

5353
{% if needs_redis %}

sentry_sdk/client.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,11 @@ def _get_options(*args, **kwargs):
122122
rv["traces_sample_rate"] = 1.0
123123

124124
if rv["event_scrubber"] is None:
125-
rv["event_scrubber"] = EventScrubber(send_default_pii=rv["send_default_pii"])
125+
rv["event_scrubber"] = EventScrubber(
126+
send_default_pii=(
127+
False if rv["send_default_pii"] is None else rv["send_default_pii"]
128+
)
129+
)
126130

127131
if rv["socket_options"] and not isinstance(rv["socket_options"], list):
128132
logger.warning(
@@ -402,7 +406,11 @@ def should_send_default_pii(self):
402406
403407
Returns whether the client should send default PII (Personally Identifiable Information) data to Sentry.
404408
"""
405-
return self.options.get("send_default_pii", False)
409+
result = self.options.get("send_default_pii")
410+
if result is None:
411+
result = not self.options["dsn"] and self.spotlight is not None
412+
413+
return result
406414

407415
@property
408416
def dsn(self):

sentry_sdk/consts.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@ class OP:
476476
# This type exists to trick mypy and PyCharm into thinking `init` and `Client`
477477
# take these arguments (even though they take opaque **kwargs)
478478
class ClientConstructor:
479+
479480
def __init__(
480481
self,
481482
dsn=None, # type: Optional[str]
@@ -493,7 +494,7 @@ def __init__(
493494
transport=None, # type: Optional[Union[sentry_sdk.transport.Transport, Type[sentry_sdk.transport.Transport], Callable[[Event], None]]]
494495
transport_queue_size=DEFAULT_QUEUE_SIZE, # type: int
495496
sample_rate=1.0, # type: float
496-
send_default_pii=False, # type: bool
497+
send_default_pii=None, # type: Optional[bool]
497498
http_proxy=None, # type: Optional[str]
498499
https_proxy=None, # type: Optional[str]
499500
ignore_errors=[], # type: Sequence[Union[type, str]] # noqa: B006
@@ -561,4 +562,4 @@ def _get_default_options():
561562
del _get_default_options
562563

563564

564-
VERSION = "2.18.0"
565+
VERSION = "2.19.0"

sentry_sdk/integrations/launchdarkly.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class LaunchDarklyHook(Hook):
5050
@property
5151
def metadata(self):
5252
# type: () -> Metadata
53-
return Metadata(name="sentry-feature-flag-recorder")
53+
return Metadata(name="sentry-flag-auditor")
5454

5555
def after_evaluation(self, series_context, data, detail):
5656
# type: (EvaluationSeriesContext, dict[Any, Any], EvaluationDetail) -> dict[Any, Any]

sentry_sdk/integrations/wsgi.py

Lines changed: 64 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import sys
2-
from contextlib import nullcontext
32
from functools import partial
43

54
import sentry_sdk
@@ -12,6 +11,7 @@
1211
)
1312
from sentry_sdk.sessions import track_session
1413
from sentry_sdk.tracing import Transaction, TRANSACTION_SOURCE_ROUTE
14+
from sentry_sdk.tracing_utils import finish_running_transaction
1515
from sentry_sdk.utils import (
1616
ContextVar,
1717
capture_internal_exceptions,
@@ -44,6 +44,9 @@ def __call__(self, status, response_headers, exc_info=None): # type: ignore
4444
pass
4545

4646

47+
MAX_TRANSACTION_DURATION_SECONDS = 5 * 60
48+
49+
4750
_wsgi_middleware_applied = ContextVar("sentry_wsgi_middleware_applied")
4851

4952
DEFAULT_TRANSACTION_NAME = "generic WSGI request"
@@ -110,6 +113,7 @@ def __call__(self, environ, start_response):
110113
scope.set_transaction_name(
111114
DEFAULT_TRANSACTION_NAME, source=TRANSACTION_SOURCE_ROUTE
112115
)
116+
current_scope = sentry_sdk.get_current_scope()
113117

114118
with track_session(scope, session_mode="request"):
115119
with capture_internal_exceptions():
@@ -120,11 +124,14 @@ def __call__(self, environ, start_response):
120124
environ, self.use_x_forwarded_for
121125
)
122126
)
127+
123128
method = environ.get("REQUEST_METHOD", "").upper()
124129
should_trace = method in self.http_methods_to_capture
130+
transaction = None
131+
125132
with sentry_sdk.continue_trace(environ):
126-
with (
127-
sentry_sdk.start_span(
133+
if should_trace:
134+
transaction = sentry_sdk.start_span(
128135
op=OP.HTTP_SERVER,
129136
name=DEFAULT_TRANSACTION_NAME,
130137
source=TRANSACTION_SOURCE_ROUTE,
@@ -133,9 +140,9 @@ def __call__(self, environ, start_response):
133140
environ, self.use_x_forwarded_for
134141
),
135142
)
136-
if should_trace
137-
else nullcontext()
138-
) as transaction:
143+
transaction.__enter__()
144+
current_scope = transaction.scope
145+
139146
try:
140147
response = self.app(
141148
environ,
@@ -146,12 +153,20 @@ def __call__(self, environ, start_response):
146153
),
147154
)
148155
except BaseException:
149-
reraise(*_capture_exception())
156+
exc_info = sys.exc_info()
157+
_capture_exception(exc_info)
158+
finish_running_transaction(transaction, exc_info)
159+
reraise(*exc_info)
150160

151161
finally:
152162
_wsgi_middleware_applied.set(False)
153163

154-
return _ScopedResponse(scope, response)
164+
return _ScopedResponse(
165+
response=response,
166+
current_scope=current_scope,
167+
isolation_scope=scope,
168+
transaction=transaction,
169+
)
155170

156171

157172
def _sentry_start_response( # type: ignore
@@ -213,13 +228,13 @@ def get_client_ip(environ):
213228
return environ.get("REMOTE_ADDR")
214229

215230

216-
def _capture_exception():
217-
# type: () -> ExcInfo
231+
def _capture_exception(exc_info=None):
232+
# type: (Optional[ExcInfo]) -> ExcInfo
218233
"""
219234
Captures the current exception and sends it to Sentry.
220235
Returns the ExcInfo tuple to it can be reraised afterwards.
221236
"""
222-
exc_info = sys.exc_info()
237+
exc_info = exc_info or sys.exc_info()
223238
e = exc_info[1]
224239

225240
# SystemExit(0) is the only uncaught exception that is expected behavior
@@ -237,7 +252,7 @@ def _capture_exception():
237252

238253
class _ScopedResponse:
239254
"""
240-
Users a separate scope for each response chunk.
255+
Use separate scopes for each response chunk.
241256
242257
This will make WSGI apps more tolerant against:
243258
- WSGI servers streaming responses from a different thread/from
@@ -246,37 +261,54 @@ class _ScopedResponse:
246261
- WSGI servers streaming responses interleaved from the same thread
247262
"""
248263

249-
__slots__ = ("_response", "_scope")
264+
__slots__ = ("_response", "_current_scope", "_isolation_scope", "_transaction")
250265

251-
def __init__(self, scope, response):
252-
# type: (sentry_sdk.scope.Scope, Iterator[bytes]) -> None
253-
self._scope = scope
266+
def __init__(
267+
self,
268+
response, # type: Iterator[bytes]
269+
current_scope, # type: sentry_sdk.scope.Scope
270+
isolation_scope, # type: sentry_sdk.scope.Scope
271+
transaction=None, # type: Optional[Transaction]
272+
):
273+
# type: (...) -> None
254274
self._response = response
275+
self._current_scope = current_scope
276+
self._isolation_scope = isolation_scope
277+
self._transaction = transaction
255278

256279
def __iter__(self):
257280
# type: () -> Iterator[bytes]
258281
iterator = iter(self._response)
259282

260-
while True:
261-
with sentry_sdk.use_isolation_scope(self._scope):
262-
try:
263-
chunk = next(iterator)
264-
except StopIteration:
265-
break
266-
except BaseException:
267-
reraise(*_capture_exception())
283+
try:
284+
while True:
285+
with sentry_sdk.use_isolation_scope(self._isolation_scope):
286+
with sentry_sdk.use_scope(self._current_scope):
287+
try:
288+
chunk = next(iterator)
289+
except StopIteration:
290+
break
291+
except BaseException:
292+
reraise(*_capture_exception())
293+
294+
yield chunk
268295

269-
yield chunk
296+
finally:
297+
with sentry_sdk.use_isolation_scope(self._isolation_scope):
298+
with sentry_sdk.use_scope(self._current_scope):
299+
finish_running_transaction(transaction=self._transaction)
270300

271301
def close(self):
272302
# type: () -> None
273-
with sentry_sdk.use_isolation_scope(self._scope):
274-
try:
275-
self._response.close() # type: ignore
276-
except AttributeError:
277-
pass
278-
except BaseException:
279-
reraise(*_capture_exception())
303+
with sentry_sdk.use_isolation_scope(self._isolation_scope):
304+
with sentry_sdk.use_scope(self._current_scope):
305+
try:
306+
finish_running_transaction(transaction=self._transaction)
307+
self._response.close() # type: ignore
308+
except AttributeError:
309+
pass
310+
except BaseException:
311+
reraise(*_capture_exception())
280312

281313

282314
def _make_wsgi_event_processor(environ, use_x_forwarded_for):

sentry_sdk/tracing.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1317,6 +1317,7 @@ def __exit__(self, ty, value, tb):
13171317

13181318
self.finish()
13191319
context.detach(self._ctx_token)
1320+
del self._ctx_token
13201321

13211322
@property
13221323
def description(self):

sentry_sdk/tracing_utils.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636

3737
from types import FrameType
3838

39+
from sentry_sdk._types import ExcInfo
40+
from threading import Timer
41+
3942

4043
SENTRY_TRACE_REGEX = re.compile(
4144
"^[ \t]*" # whitespace
@@ -731,3 +734,15 @@ def get_current_span(scope=None):
731734
LOW_QUALITY_TRANSACTION_SOURCES,
732735
SENTRY_TRACE_HEADER_NAME,
733736
)
737+
738+
if TYPE_CHECKING:
739+
from sentry_sdk.tracing import Span
740+
741+
742+
def finish_running_transaction(transaction=None, exc_info=None):
743+
# type: (Optional[sentry_sdk.Transaction], Optional[ExcInfo]) -> None
744+
if transaction is not None and hasattr(transaction, "_ctx_token"):
745+
if exc_info is not None:
746+
transaction.__exit__(*exc_info)
747+
else:
748+
transaction.__exit__(None, None, None)

0 commit comments

Comments
 (0)