Skip to content

Commit 4f4df13

Browse files
merge master
2 parents 5343aaa + 66824a4 commit 4f4df13

38 files changed

Lines changed: 1113 additions & 515 deletions

.git-blame-ignore-revs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ afea4a017bf13f78e82f725ea9d6a56a8e02cb34
33
23a340a9dca60eea36de456def70c00952a33556
44
973dda79311cf6b9cb8f1ba67ca0515dfaf9f49c
55
e275c9e94323b429f39196881fb992d81a2e52ea
6+
015ff31b48d322ddf7270b9391ef2ed16f7a42a3

.github/workflows/ai-integration-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
token: ${{ secrets.GITHUB_TOKEN }}
3535

3636
- name: Run Python SDK Tests
37-
uses: getsentry/testing-ai-sdk-integrations@18229d1da4bb8120ce923bdf7aac00fcf6f38311
37+
uses: getsentry/testing-ai-sdk-integrations@1668d0ee106d1ac7cab0bb2e5bafa20eb0fddfa4
3838
env:
3939
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4040
with:

.github/workflows/changelog-preview.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ permissions:
1515

1616
jobs:
1717
changelog-preview:
18-
uses: getsentry/craft/.github/workflows/changelog-preview.yml@bae212ca7aec50bb716eafd387c80bcfb28da937 # v2
18+
uses: getsentry/craft/.github/workflows/changelog-preview.yml@bc2e6a9952e62250e5469d5a853a7a438692ccc1 # v2
1919
secrets: inherit

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
steps:
2323
- name: Get auth token
2424
id: token
25-
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
25+
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
2626
with:
2727
app-id: ${{ vars.SENTRY_RELEASE_BOT_CLIENT_ID }}
2828
private-key: ${{ secrets.SENTRY_RELEASE_BOT_PRIVATE_KEY }}
@@ -31,7 +31,7 @@ jobs:
3131
token: ${{ steps.token.outputs.token }}
3232
fetch-depth: 0
3333
- name: Prepare release
34-
uses: getsentry/craft@bae212ca7aec50bb716eafd387c80bcfb28da937 # v2.26.3
34+
uses: getsentry/craft@bc2e6a9952e62250e5469d5a853a7a438692ccc1 # v2.26.5
3535
env:
3636
GITHUB_TOKEN: ${{ steps.token.outputs.token }}
3737
with:

.github/workflows/validate-pr.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
permissions:
1111
pull-requests: write
1212
steps:
13-
- uses: getsentry/github-workflows/validate-pr@43bf14b190c12080cfbedf2d2c82337bc559a0e1
13+
- uses: getsentry/github-workflows/validate-pr@b6d9e26d1c5bb01362670e13288b2284bab8cbf9
1414
with:
1515
app-id: ${{ vars.SDK_MAINTAINER_BOT_APP_ID }}
1616
private-key: ${{ secrets.SDK_MAINTAINER_BOT_PRIVATE_KEY }}

scripts/populate_tox/package_dependencies.jsonl

Lines changed: 12 additions & 13 deletions
Large diffs are not rendered by default.

scripts/populate_tox/releases.jsonl

Lines changed: 26 additions & 26 deletions
Large diffs are not rendered by default.

scripts/test-lambda-locally/uv.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sentry_sdk/_span_batcher.py

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@
1414
if TYPE_CHECKING:
1515
from typing import Any, Callable, Optional
1616

17-
from sentry_sdk.traces import StreamedSpan
17+
from sentry_sdk._types import SpanJSON
1818

1919

20-
class SpanBatcher(Batcher["StreamedSpan"]):
20+
class SpanBatcher(Batcher["SpanJSON"]):
2121
# MAX_BEFORE_FLUSH should be lower than MAX_BEFORE_DROP, so that there is
2222
# a bit of a buffer for spans that appear between the trigger to flush
2323
# and actually flushing the buffer.
@@ -43,7 +43,7 @@ def __init__(
4343
# by trace_id, so that we can then send the buckets each in its own
4444
# envelope.
4545
# trace_id -> span buffer
46-
self._span_buffer: dict[str, list["StreamedSpan"]] = defaultdict(list)
46+
self._span_buffer: dict[str, list["SpanJSON"]] = defaultdict(list)
4747
self._running_size: dict[str, int] = defaultdict(lambda: 0)
4848
self._capture_func = capture_func
4949
self._record_lost_func = record_lost_func
@@ -100,7 +100,7 @@ def _flush_loop(self) -> None:
100100
self._flush()
101101
self._last_full_flush = time.monotonic()
102102

103-
def add(self, span: "StreamedSpan") -> None:
103+
def add(self, span: "SpanJSON") -> None:
104104
# Bail out if the current thread is already executing batcher code.
105105
# This prevents deadlocks when code running inside the batcher (e.g.
106106
# _add_to_envelope during flush, or _flush_event.wait/set) triggers
@@ -116,7 +116,7 @@ def add(self, span: "StreamedSpan") -> None:
116116
return None
117117

118118
with self._lock:
119-
size = len(self._span_buffer[span.trace_id])
119+
size = len(self._span_buffer[span["trace_id"]])
120120
if size >= self.MAX_BEFORE_DROP:
121121
self._record_lost_func(
122122
reason="queue_overflow",
@@ -125,14 +125,15 @@ def add(self, span: "StreamedSpan") -> None:
125125
)
126126
return None
127127

128-
self._span_buffer[span.trace_id].append(span)
129-
self._running_size[span.trace_id] += self._estimate_size(span)
128+
self._span_buffer[span["trace_id"]].append(span)
129+
self._running_size[span["trace_id"]] += self._estimate_size(span)
130130

131131
if (
132132
size + 1 >= self.MAX_BEFORE_FLUSH
133-
or self._running_size[span.trace_id] >= self.MAX_BYTES_BEFORE_FLUSH
133+
or self._running_size[span["trace_id"]]
134+
>= self.MAX_BYTES_BEFORE_FLUSH
134135
):
135-
self._pending_flush.add(span.trace_id)
136+
self._pending_flush.add(span["trace_id"])
136137
notify = True
137138
else:
138139
notify = False
@@ -143,12 +144,12 @@ def add(self, span: "StreamedSpan") -> None:
143144
self._active.flag = False
144145

145146
@staticmethod
146-
def _estimate_size(item: "StreamedSpan") -> int:
147+
def _estimate_size(item: "SpanJSON") -> int:
147148
# Rough estimate of serialized span size that's quick to compute.
148149
# 210 is the rough size of the payload without attributes, and then we
149150
# estimate the attributes separately.
150151
estimate = 210
151-
for value in item._attributes.values():
152+
for value in (item.get("attributes") or {}).values():
152153
estimate += 50
153154

154155
if isinstance(value, str):
@@ -159,26 +160,15 @@ def _estimate_size(item: "StreamedSpan") -> int:
159160
return estimate
160161

161162
@staticmethod
162-
def _to_transport_format(item: "StreamedSpan") -> "Any":
163-
res: "dict[str, Any]" = {
164-
"trace_id": item.trace_id,
165-
"span_id": item.span_id,
166-
"name": item._name if item._name is not None else "<unlabeled span>",
167-
"status": item._status,
168-
"is_segment": item._is_segment(),
169-
"start_timestamp": item._start_timestamp.timestamp(),
170-
}
171-
172-
if item._end_timestamp:
173-
res["end_timestamp"] = item._end_timestamp.timestamp()
174-
175-
if item._parent_span_id:
176-
res["parent_span_id"] = item._parent_span_id
177-
178-
if item._attributes:
163+
def _to_transport_format(item: "SpanJSON") -> "Any":
164+
res = {k: v for k, v in item.items() if k not in ("_segment_span",)}
165+
166+
if item.get("attributes"):
179167
res["attributes"] = {
180-
k: serialize_attribute(v) for (k, v) in item._attributes.items()
168+
k: serialize_attribute(v) for (k, v) in item["attributes"].items()
181169
}
170+
else:
171+
del res["attributes"]
182172

183173
return res
184174

@@ -202,7 +192,7 @@ def _flush(self, only_pending: bool = False) -> None:
202192
if not spans:
203193
continue
204194

205-
dsc = spans[0]._dynamic_sampling_context()
195+
dsc = spans[0]["_segment_span"]._dynamic_sampling_context()
206196

207197
# Max per envelope is 1000, so if we happen to have more than
208198
# 1000 spans in one bucket, we'll need to separate them.

sentry_sdk/_types.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ def substituted_because_contains_sensitive_data(cls) -> "AnnotatedValue":
145145

146146
from typing_extensions import Literal, TypedDict
147147

148+
import sentry_sdk
149+
148150
class SDKInfo(TypedDict):
149151
name: str
150152
version: str
@@ -318,6 +320,22 @@ class SDKInfo(TypedDict):
318320

319321
MetricProcessor = Callable[[Metric, Hint], Optional[Metric]]
320322

323+
SpanJSON = TypedDict(
324+
"SpanJSON",
325+
{
326+
"trace_id": str,
327+
"span_id": str,
328+
"parent_span_id": NotRequired[str],
329+
"name": str,
330+
"status": str,
331+
"is_segment": bool,
332+
"start_timestamp": float,
333+
"end_timestamp": NotRequired[float],
334+
"attributes": NotRequired[Attributes],
335+
"_segment_span": NotRequired["sentry_sdk.traces.StreamedSpan"],
336+
},
337+
)
338+
321339
# TODO: Make a proper type definition for this (PRs welcome!)
322340
Breadcrumb = Dict[str, Any]
323341

0 commit comments

Comments
 (0)