Skip to content

Commit 1922a8a

Browse files
Merge branch 'master' into major/3.0
2 parents dc22185 + 42aa532 commit 1922a8a

6 files changed

Lines changed: 672 additions & 175 deletions

File tree

‎CHANGELOG.md‎

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

3+
## 2.69.0
4+
5+
### New Features ✨
6+
7+
#### Other
8+
9+
- (aiohttp) Add `http.route` attribute by @alexander-alderman-webb in [#7341](https://github.com/getsentry/sentry-python/pull/7341)
10+
- (bottle) Add `http.route` attribute by @alexander-alderman-webb in [#7343](https://github.com/getsentry/sentry-python/pull/7343)
11+
- (clickhouse_driver) Set breadcrumbs in the streaming trace lifecycle by @alexander-alderman-webb in [#7325](https://github.com/getsentry/sentry-python/pull/7325)
12+
- (docs) Add Plausible analytics to Sphinx docs by @ericapisani in [#7319](https://github.com/getsentry/sentry-python/pull/7319)
13+
- (falcon) Add `http.route` attribute by @alexander-alderman-webb in [#7340](https://github.com/getsentry/sentry-python/pull/7340)
14+
- (fastapi) Add `http.route` attribute by @alexander-alderman-webb in [#7322](https://github.com/getsentry/sentry-python/pull/7322)
15+
- (flask) Add `http.route` attribute by @alexander-alderman-webb in [#7344](https://github.com/getsentry/sentry-python/pull/7344)
16+
- (pyramid) Add `http.route` attribute by @alexander-alderman-webb in [#7347](https://github.com/getsentry/sentry-python/pull/7347)
17+
- (quart) Add `http.route` attribute by @alexander-alderman-webb in [#7348](https://github.com/getsentry/sentry-python/pull/7348)
18+
- (sqlalchemy) Add more db system names for span data by @ericapisani in [#7329](https://github.com/getsentry/sentry-python/pull/7329)
19+
- (starlette) Add `http.route` attribute by @alexander-alderman-webb in [#7338](https://github.com/getsentry/sentry-python/pull/7338)
20+
- (types) Export SpanJSON type by @ericapisani in [#7331](https://github.com/getsentry/sentry-python/pull/7331)
21+
- Add Python 3.15 to test matrix by @sentrivana in [#7326](https://github.com/getsentry/sentry-python/pull/7326)
22+
23+
### Bug Fixes 🐛
24+
25+
#### Mcp
26+
27+
- Handle `None` arguments in tool and prompt handlers by @alexander-alderman-webb in [#7387](https://github.com/getsentry/sentry-python/pull/7387)
28+
- Don't report stateless StreamableHTTP servers as stdio by @Snaylaker in [#7224](https://github.com/getsentry/sentry-python/pull/7224)
29+
30+
#### Openai
31+
32+
- Read `input_text` parts for the Responses API by @alexander-alderman-webb in [#7333](https://github.com/getsentry/sentry-python/pull/7333)
33+
- Check `Response.output` is a `list` before iterating by @alexander-alderman-webb in [#7238](https://github.com/getsentry/sentry-python/pull/7238)
34+
35+
#### Starlette
36+
37+
- Use `url` transaction source for host routing by @mjq in [#7266](https://github.com/getsentry/sentry-python/pull/7266)
38+
- Set transaction name on current scope in sync handler by @mjq in [#7201](https://github.com/getsentry/sentry-python/pull/7201)
39+
40+
#### Other
41+
42+
- (batcher) Do not let a failed flush kill the flusher thread (#7138) by @zkasuran in [#7186](https://github.com/getsentry/sentry-python/pull/7186)
43+
- (boto3) Fix botocore SigV4 failures caused by post-sign trace propagation by @pabloDeputter in [#7050](https://github.com/getsentry/sentry-python/pull/7050)
44+
- (httpx,httpx2) Always capture breadcrumb by @sentrivana in [#7351](https://github.com/getsentry/sentry-python/pull/7351)
45+
- (mcp,langchain) Add mechanism to captured exceptions by @gmassello in [#7226](https://github.com/getsentry/sentry-python/pull/7226)
46+
- (openai-agents) Use `isinstance` to determine tool type by @alexander-alderman-webb in [#7412](https://github.com/getsentry/sentry-python/pull/7412)
47+
- (quart) Skip quart-flask-patch and adjust error test for quart>=0.23 by @ericapisani in [#7320](https://github.com/getsentry/sentry-python/pull/7320)
48+
- Allow to correctly compare parsed versions by @sentrivana in [#7184](https://github.com/getsentry/sentry-python/pull/7184)
49+
50+
### Internal Changes 🔧
51+
52+
#### Openai Agents
53+
54+
- Capture spans instead of reading from span recorder by @alexander-alderman-webb in [#7404](https://github.com/getsentry/sentry-python/pull/7404)
55+
- Pin `openai` version when incompatible by @alexander-alderman-webb in [#7236](https://github.com/getsentry/sentry-python/pull/7236)
56+
57+
#### Pydantic Ai
58+
59+
- Replace individual hooks with `hooks.on.model_request` by @alexander-alderman-webb in [#7327](https://github.com/getsentry/sentry-python/pull/7327)
60+
- Fix instructions test for pydantic-ai >=2.36.0 by @ericapisani in [#7321](https://github.com/getsentry/sentry-python/pull/7321)
61+
62+
#### Other
63+
64+
- (aiohttp) Remove dead segment name code by @mjq in [#7284](https://github.com/getsentry/sentry-python/pull/7284)
65+
- (anthropic) Include `StreamedSpan` in type annotations by @alexander-alderman-webb in [#7373](https://github.com/getsentry/sentry-python/pull/7373)
66+
- (mcp) Inline `_extract_handler_data_from_args()` by @alexander-alderman-webb in [#7386](https://github.com/getsentry/sentry-python/pull/7386)
67+
- (quart) Fix flake caused by flushing spans on segment end by @alexander-alderman-webb in [#7240](https://github.com/getsentry/sentry-python/pull/7240)
68+
- (stdlib) Remove urllib3 workaround by @pabloDeputter in [#7283](https://github.com/getsentry/sentry-python/pull/7283)
69+
- Add `openai-agents` to uv typing group by @alexander-alderman-webb in [#7415](https://github.com/getsentry/sentry-python/pull/7415)
70+
- Add `aiohttp` to uv typing group by @alexander-alderman-webb in [#7395](https://github.com/getsentry/sentry-python/pull/7395)
71+
- Isolate `httpx` test suite from `httpx2` by @ZaafirRizwan in [#7398](https://github.com/getsentry/sentry-python/pull/7398)
72+
- Remove `test_langchain_embeddings_error_handling()` by @alexander-alderman-webb in [#7389](https://github.com/getsentry/sentry-python/pull/7389)
73+
- Add `tiktoken` to uv typing group by @alexander-alderman-webb in [#7394](https://github.com/getsentry/sentry-python/pull/7394)
74+
- Reference renamed coverage action by @MathurAditya724 in [#7371](https://github.com/getsentry/sentry-python/pull/7371)
75+
- Remove flaky detector by @sl0thentr0py in [#7363](https://github.com/getsentry/sentry-python/pull/7363)
76+
- Add `openai` to uv typing group by @alexander-alderman-webb in [#7334](https://github.com/getsentry/sentry-python/pull/7334)
77+
- 🤖 Update test matrix with new releases (08/31) by @github-actions in [#7303](https://github.com/getsentry/sentry-python/pull/7303)
78+
- Add `anthropic` to uv typing group by @alexander-alderman-webb in [#7324](https://github.com/getsentry/sentry-python/pull/7324)
79+
- Add `google-genai` to uv typing group by @alexander-alderman-webb in [#7323](https://github.com/getsentry/sentry-python/pull/7323)
80+
- Use tagged versions for `getsentry/codecov-action` by @alexander-alderman-webb in [#7241](https://github.com/getsentry/sentry-python/pull/7241)
81+
- Update test matrix with new releases (08/24) by @alexander-alderman-webb in [#7228](https://github.com/getsentry/sentry-python/pull/7228)
82+
- Add `httpx` dependency to tests relying on `get_model_response()` by @alexander-alderman-webb in [#7235](https://github.com/getsentry/sentry-python/pull/7235)
83+
- Access the 'type' in an event using `.get` by @ericapisani in [#7239](https://github.com/getsentry/sentry-python/pull/7239)
84+
385
## 2.68.1
486

587
### `enable_logs`

‎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.68.1"
34+
release = "2.69.0"
3535
version = ".".join(release.split(".")[:2]) # The short X.Y version.
3636

3737

‎sentry_sdk/consts.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1802,4 +1802,4 @@ def _get_default_options() -> "dict[str, Any]":
18021802
del _get_default_options
18031803

18041804

1805-
VERSION = "2.68.1"
1805+
VERSION = "2.69.0"

‎setup.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def get_file_text(file_name):
2222

2323
setup(
2424
name="sentry-sdk",
25-
version="2.68.1",
25+
version="2.69.0",
2626
author="Sentry Team and Contributors",
2727
author_email="hello@sentry.io",
2828
url="https://github.com/getsentry/sentry-python",

‎tests/integrations/cohere/test_cohere.py‎

Lines changed: 145 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -249,20 +249,43 @@ def test_streaming_chat(
249249
assert span["data"]["gen_ai.usage.total_tokens"] == 30
250250

251251

252-
def test_bad_chat(sentry_init, capture_events):
253-
sentry_init(integrations=[CohereIntegration()], traces_sample_rate=1.0)
254-
events = capture_events()
255-
256-
client = Client(api_key="z")
257-
HTTPXClient.request = mock.Mock(
258-
side_effect=httpx.HTTPError("API rate limit reached")
252+
@pytest.mark.parametrize("span_streaming", [True, False])
253+
def test_bad_chat(sentry_init, capture_events, capture_items, span_streaming):
254+
sentry_init(
255+
integrations=[CohereIntegration()],
256+
traces_sample_rate=1.0,
257+
trace_lifecycle="stream" if span_streaming else "static",
259258
)
260-
with pytest.raises(httpx.HTTPError):
261-
client.chat(model="some-model", message="hello")
262259

263-
(event, transaction) = events
264-
assert event["level"] == "error"
265-
assert transaction["contexts"]["trace"]["status"] == "internal_error"
260+
if span_streaming:
261+
items = capture_items("event", "span")
262+
263+
client = Client(api_key="z")
264+
HTTPXClient.request = mock.Mock(
265+
side_effect=httpx.HTTPError("API rate limit reached")
266+
)
267+
with pytest.raises(httpx.HTTPError):
268+
client.chat(model="some-model", message="hello")
269+
270+
(event,) = (item.payload for item in items if item.type == "event")
271+
assert event["level"] == "error"
272+
273+
sentry_sdk.flush()
274+
(span,) = (item.payload for item in items if item.type == "span")
275+
assert span["status"] == "error"
276+
else:
277+
events = capture_events()
278+
279+
client = Client(api_key="z")
280+
HTTPXClient.request = mock.Mock(
281+
side_effect=httpx.HTTPError("API rate limit reached")
282+
)
283+
with pytest.raises(httpx.HTTPError):
284+
client.chat(model="some-model", message="hello")
285+
286+
(event, transaction) = events
287+
assert event["level"] == "error"
288+
assert transaction["contexts"]["trace"]["status"] == "internal_error"
266289

267290

268291
def test_span_status_error(sentry_init, capture_events):
@@ -386,74 +409,138 @@ def test_embed(
386409
assert span["data"]["gen_ai.usage.total_tokens"] == 10
387410

388411

389-
def test_span_origin_chat(sentry_init, capture_events):
412+
@pytest.mark.parametrize("span_streaming", [True, False])
413+
def test_span_origin_chat(sentry_init, capture_events, capture_items, span_streaming):
390414
sentry_init(
391415
integrations=[CohereIntegration()],
392416
traces_sample_rate=1.0,
417+
trace_lifecycle="stream" if span_streaming else "static",
393418
)
394-
events = capture_events()
395419

396-
client = Client(api_key="z")
397-
HTTPXClient.request = mock.Mock(
398-
return_value=httpx.Response(
399-
200,
400-
json={
401-
"text": "the model response",
402-
"meta": {
403-
"billed_units": {
404-
"output_tokens": 10,
405-
"input_tokens": 20,
406-
}
420+
if span_streaming:
421+
items = capture_items("span")
422+
423+
client = Client(api_key="z")
424+
HTTPXClient.request = mock.Mock(
425+
return_value=httpx.Response(
426+
200,
427+
json={
428+
"text": "the model response",
429+
"meta": {
430+
"billed_units": {
431+
"output_tokens": 10,
432+
"input_tokens": 20,
433+
}
434+
},
407435
},
408-
},
436+
)
409437
)
410-
)
411438

412-
with start_transaction(name="cohere tx"):
413-
client.chat(
414-
model="some-model",
415-
chat_history=[ChatMessage(role="SYSTEM", message="some context")],
416-
message="hello",
417-
).text
439+
with start_transaction(name="cohere tx"):
440+
client.chat(
441+
model="some-model",
442+
chat_history=[ChatMessage(role="SYSTEM", message="some context")],
443+
message="hello",
444+
).text
418445

419-
(event,) = events
446+
sentry_sdk.flush()
447+
(span,) = (item.payload for item in items)
448+
assert span["attributes"]["sentry.origin"] == "auto.ai.cohere"
449+
else:
450+
events = capture_events()
420451

421-
assert event["contexts"]["trace"]["origin"] == "manual"
422-
assert event["spans"][0]["origin"] == "auto.ai.cohere"
452+
client = Client(api_key="z")
453+
HTTPXClient.request = mock.Mock(
454+
return_value=httpx.Response(
455+
200,
456+
json={
457+
"text": "the model response",
458+
"meta": {
459+
"billed_units": {
460+
"output_tokens": 10,
461+
"input_tokens": 20,
462+
}
463+
},
464+
},
465+
)
466+
)
467+
468+
with start_transaction(name="cohere tx"):
469+
client.chat(
470+
model="some-model",
471+
chat_history=[ChatMessage(role="SYSTEM", message="some context")],
472+
message="hello",
473+
).text
474+
475+
(event,) = events
476+
477+
assert event["contexts"]["trace"]["origin"] == "manual"
478+
assert event["spans"][0]["origin"] == "auto.ai.cohere"
423479

424480

425-
def test_span_origin_embed(sentry_init, capture_events):
481+
@pytest.mark.parametrize("span_streaming", [True, False])
482+
def test_span_origin_embed(sentry_init, capture_events, capture_items, span_streaming):
426483
sentry_init(
427484
integrations=[CohereIntegration()],
428485
traces_sample_rate=1.0,
486+
trace_lifecycle="stream" if span_streaming else "static",
429487
)
430-
events = capture_events()
431488

432-
client = Client(api_key="z")
433-
HTTPXClient.request = mock.Mock(
434-
return_value=httpx.Response(
435-
200,
436-
json={
437-
"response_type": "embeddings_floats",
438-
"id": "1",
439-
"texts": ["hello"],
440-
"embeddings": [[1.0, 2.0, 3.0]],
441-
"meta": {
442-
"billed_units": {
443-
"input_tokens": 10,
444-
}
489+
if span_streaming:
490+
items = capture_items("span")
491+
492+
client = Client(api_key="z")
493+
HTTPXClient.request = mock.Mock(
494+
return_value=httpx.Response(
495+
200,
496+
json={
497+
"response_type": "embeddings_floats",
498+
"id": "1",
499+
"texts": ["hello"],
500+
"embeddings": [[1.0, 2.0, 3.0]],
501+
"meta": {
502+
"billed_units": {
503+
"input_tokens": 10,
504+
}
505+
},
445506
},
446-
},
507+
)
447508
)
448-
)
449509

450-
with start_transaction(name="cohere tx"):
451-
client.embed(texts=["hello"], model="text-embedding-3-large")
510+
with start_transaction(name="cohere tx"):
511+
client.embed(texts=["hello"], model="text-embedding-3-large")
512+
513+
sentry_sdk.flush()
514+
(span,) = (item.payload for item in items)
515+
assert span["attributes"]["sentry.origin"] == "auto.ai.cohere"
516+
else:
517+
events = capture_events()
518+
519+
client = Client(api_key="z")
520+
HTTPXClient.request = mock.Mock(
521+
return_value=httpx.Response(
522+
200,
523+
json={
524+
"response_type": "embeddings_floats",
525+
"id": "1",
526+
"texts": ["hello"],
527+
"embeddings": [[1.0, 2.0, 3.0]],
528+
"meta": {
529+
"billed_units": {
530+
"input_tokens": 10,
531+
}
532+
},
533+
},
534+
)
535+
)
536+
537+
with start_transaction(name="cohere tx"):
538+
client.embed(texts=["hello"], model="text-embedding-3-large")
452539

453-
(event,) = events
540+
(event,) = events
454541

455-
assert event["contexts"]["trace"]["origin"] == "manual"
456-
assert event["spans"][0]["origin"] == "auto.ai.cohere"
542+
assert event["contexts"]["trace"]["origin"] == "manual"
543+
assert event["spans"][0]["origin"] == "auto.ai.cohere"
457544

458545

459546
# data_collection config, send_default_pii, include_prompts, expect_inputs, expect_outputs

0 commit comments

Comments
 (0)