From cdd292f9cfba151b5a99b182400d3e43d8de8a20 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Fri, 10 Apr 2026 09:06:39 +0200 Subject: [PATCH 1/4] ci: test From 3ad03c3f1f127733a0468b3c01379a4c1c5650f9 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Fri, 10 Apr 2026 09:52:17 +0200 Subject: [PATCH 2/4] pin tokenizers --- scripts/populate_tox/config.py | 3 +++ tox.ini | 17 +++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/scripts/populate_tox/config.py b/scripts/populate_tox/config.py index d0d884150a..7dda5f1c72 100644 --- a/scripts/populate_tox/config.py +++ b/scripts/populate_tox/config.py @@ -18,6 +18,9 @@ "deps": { "*": ["pytest-asyncio"], "<0.50": ["httpx<0.28.0"], + # tokenizers dropped Python 3.8 support, but didn't update package metadata. + # https://github.com/huggingface/tokenizers/commit/f4c9fd7f402fc794df8f1b547a95ee5305f9fe62 + "py3.8": ["tokenizors<0.20.4"], }, "python": ">=3.8", }, diff --git a/tox.ini b/tox.ini index 1780891a72..a74a61923d 100644 --- a/tox.ini +++ b/tox.ini @@ -102,9 +102,9 @@ envlist = # ~~~ AI ~~~ {py3.8,py3.11,py3.12}-anthropic-v0.16.0 - {py3.8,py3.11,py3.12}-anthropic-v0.39.0 - {py3.8,py3.12,py3.13}-anthropic-v0.62.0 - {py3.9,py3.13,py3.14,py3.14t}-anthropic-v0.86.0 + {py3.8,py3.11,py3.12}-anthropic-v0.42.0 + {py3.8,py3.12,py3.13}-anthropic-v0.68.2 + {py3.9,py3.13,py3.14,py3.14t}-anthropic-v0.93.0 {py3.9,py3.13,py3.14,py3.14t}-anthropic-latest {py3.9,py3.10,py3.11}-cohere-v5.4.0 @@ -515,13 +515,14 @@ deps = # ~~~ AI ~~~ anthropic-v0.16.0: anthropic==0.16.0 - anthropic-v0.39.0: anthropic==0.39.0 - anthropic-v0.62.0: anthropic==0.62.0 - anthropic-v0.86.0: anthropic==0.86.0 - anthropic-latest: anthropic==0.86.0 + anthropic-v0.42.0: anthropic==0.42.0 + anthropic-v0.68.2: anthropic==0.68.2 + anthropic-v0.93.0: anthropic==0.93.0 + anthropic-latest: anthropic==0.93.0 anthropic: pytest-asyncio anthropic-v0.16.0: httpx<0.28.0 - anthropic-v0.39.0: httpx<0.28.0 + anthropic-v0.42.0: httpx<0.28.0 + {py3.8}-anthropic: tokenizors<0.20.4 cohere-v5.4.0: cohere==5.4.0 cohere-v5.10.0: cohere==5.10.0 From a60f8faada036736853b60665f6205194d2307b6 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Fri, 10 Apr 2026 10:04:04 +0200 Subject: [PATCH 3/4] fix typo --- scripts/populate_tox/config.py | 2 +- tox.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/populate_tox/config.py b/scripts/populate_tox/config.py index 7dda5f1c72..ba2f4dc6d5 100644 --- a/scripts/populate_tox/config.py +++ b/scripts/populate_tox/config.py @@ -20,7 +20,7 @@ "<0.50": ["httpx<0.28.0"], # tokenizers dropped Python 3.8 support, but didn't update package metadata. # https://github.com/huggingface/tokenizers/commit/f4c9fd7f402fc794df8f1b547a95ee5305f9fe62 - "py3.8": ["tokenizors<0.20.4"], + "py3.8": ["tokenizers<0.20.4"], }, "python": ">=3.8", }, diff --git a/tox.ini b/tox.ini index a74a61923d..956ff86b8b 100644 --- a/tox.ini +++ b/tox.ini @@ -522,7 +522,7 @@ deps = anthropic: pytest-asyncio anthropic-v0.16.0: httpx<0.28.0 anthropic-v0.42.0: httpx<0.28.0 - {py3.8}-anthropic: tokenizors<0.20.4 + {py3.8}-anthropic: tokenizers<0.20.4 cohere-v5.4.0: cohere==5.4.0 cohere-v5.10.0: cohere==5.10.0 From 1b0770513b82108b8a3d0f0658b4597ce66d021d Mon Sep 17 00:00:00 2001 From: Alex Alderman Webb Date: Fri, 10 Apr 2026 15:15:26 +0200 Subject: [PATCH 4/4] fix(opentelemetry): Handle `None` span context (#5968) --- .../opentelemetry/span_processor.py | 20 ++++++++++++------- .../opentelemetry/test_span_processor.py | 20 ++++++++++++++----- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/sentry_sdk/integrations/opentelemetry/span_processor.py b/sentry_sdk/integrations/opentelemetry/span_processor.py index 282edbe2ab..8a589af308 100644 --- a/sentry_sdk/integrations/opentelemetry/span_processor.py +++ b/sentry_sdk/integrations/opentelemetry/span_processor.py @@ -34,6 +34,7 @@ if TYPE_CHECKING: from typing import Any, Optional, Union from opentelemetry import context as context_api + from opentelemetry.trace import SpanContext from sentry_sdk._types import Event, Hint OPEN_TELEMETRY_CONTEXT = "otel" @@ -124,13 +125,16 @@ def on_start( if client.options["instrumenter"] != INSTRUMENTER.OTEL: return - if not otel_span.get_span_context().is_valid: + span_context = otel_span.get_span_context() + if span_context is None or not span_context.is_valid: return if self._is_sentry_span(otel_span): return - trace_data = self._get_trace_data(otel_span, parent_context) + trace_data = self._get_trace_data( + span_context, otel_span.parent, parent_context + ) parent_span_id = trace_data["parent_span_id"] sentry_parent_span = ( @@ -183,7 +187,7 @@ def on_end(self, otel_span: "OTelSpan") -> None: return span_context = otel_span.get_span_context() - if not span_context.is_valid: + if span_context is None or not span_context.is_valid: return span_id = format_span_id(span_context.span_id) @@ -255,13 +259,15 @@ def _get_otel_context(self, otel_span: "OTelSpan") -> "dict[str, Any]": return ctx def _get_trace_data( - self, otel_span: "OTelSpan", parent_context: "Optional[context_api.Context]" + self, + span_context: "SpanContext", + parent_span_context: "Optional[SpanContext]", + parent_context: "Optional[context_api.Context]", ) -> "dict[str, Any]": """ - Extracts tracing information from one OTel span and its parent OTel context. + Extracts tracing information from one OTel span's context and its parent OTel context. """ trace_data: "dict[str, Any]" = {} - span_context = otel_span.get_span_context() span_id = format_span_id(span_context.span_id) trace_data["span_id"] = span_id @@ -270,7 +276,7 @@ def _get_trace_data( trace_data["trace_id"] = trace_id parent_span_id = ( - format_span_id(otel_span.parent.span_id) if otel_span.parent else None + format_span_id(parent_span_context.span_id) if parent_span_context else None ) trace_data["parent_span_id"] = parent_span_id diff --git a/tests/integrations/opentelemetry/test_span_processor.py b/tests/integrations/opentelemetry/test_span_processor.py index af5cbdd3fb..e1cd849b94 100644 --- a/tests/integrations/opentelemetry/test_span_processor.py +++ b/tests/integrations/opentelemetry/test_span_processor.py @@ -68,7 +68,9 @@ def test_get_trace_data_with_span_and_trace(): parent_context = {} span_processor = SentrySpanProcessor() - sentry_trace_data = span_processor._get_trace_data(otel_span, parent_context) + sentry_trace_data = span_processor._get_trace_data( + otel_span.get_span_context(), otel_span.parent, parent_context + ) assert sentry_trace_data["trace_id"] == "1234567890abcdef1234567890abcdef" assert sentry_trace_data["span_id"] == "1234567890abcdef" assert sentry_trace_data["parent_span_id"] is None @@ -90,7 +92,9 @@ def test_get_trace_data_with_span_and_trace_and_parent(): parent_context = {} span_processor = SentrySpanProcessor() - sentry_trace_data = span_processor._get_trace_data(otel_span, parent_context) + sentry_trace_data = span_processor._get_trace_data( + otel_span.get_span_context(), otel_span.parent, parent_context + ) assert sentry_trace_data["trace_id"] == "1234567890abcdef1234567890abcdef" assert sentry_trace_data["span_id"] == "1234567890abcdef" assert sentry_trace_data["parent_span_id"] == "abcdef1234567890" @@ -121,7 +125,9 @@ def test_get_trace_data_with_sentry_trace(): ], ): span_processor = SentrySpanProcessor() - sentry_trace_data = span_processor._get_trace_data(otel_span, parent_context) + sentry_trace_data = span_processor._get_trace_data( + otel_span.get_span_context(), otel_span.parent, parent_context + ) assert sentry_trace_data["trace_id"] == "1234567890abcdef1234567890abcdef" assert sentry_trace_data["span_id"] == "1234567890abcdef" assert sentry_trace_data["parent_span_id"] == "abcdef1234567890" @@ -138,7 +144,9 @@ def test_get_trace_data_with_sentry_trace(): ], ): span_processor = SentrySpanProcessor() - sentry_trace_data = span_processor._get_trace_data(otel_span, parent_context) + sentry_trace_data = span_processor._get_trace_data( + otel_span.get_span_context(), otel_span.parent, parent_context + ) assert sentry_trace_data["trace_id"] == "1234567890abcdef1234567890abcdef" assert sentry_trace_data["span_id"] == "1234567890abcdef" assert sentry_trace_data["parent_span_id"] == "abcdef1234567890" @@ -175,7 +183,9 @@ def test_get_trace_data_with_sentry_trace_and_baggage(): ], ): span_processor = SentrySpanProcessor() - sentry_trace_data = span_processor._get_trace_data(otel_span, parent_context) + sentry_trace_data = span_processor._get_trace_data( + otel_span.get_span_context(), otel_span.parent, parent_context + ) assert sentry_trace_data["trace_id"] == "1234567890abcdef1234567890abcdef" assert sentry_trace_data["span_id"] == "1234567890abcdef" assert sentry_trace_data["parent_span_id"] == "abcdef1234567890"