Skip to content

Commit 7becc66

Browse files
merge master
2 parents 4279ba5 + 0357ef0 commit 7becc66

File tree

4 files changed

+86
-16
lines changed

4 files changed

+86
-16
lines changed

sentry_sdk/_span_batcher.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,15 @@ def add(self, span: "StreamedSpan") -> None:
7070
@staticmethod
7171
def _to_transport_format(item: "StreamedSpan") -> "Any":
7272
# TODO[span-first]
73-
res: "dict[str, Any]" = {}
73+
res: "dict[str, Any]" = {
74+
"name": item.name,
75+
}
76+
77+
if item._attributes:
78+
res["attributes"] = {
79+
k: serialize_attribute(v) for (k, v) in item._attributes.items()
80+
}
81+
7482
return res
7583

7684
def _flush(self) -> None:

sentry_sdk/client.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
from sentry_sdk.scope import Scope
7070
from sentry_sdk.session import Session
7171
from sentry_sdk.spotlight import SpotlightClient
72+
from sentry_sdk.traces import StreamedSpan
7273
from sentry_sdk.transport import Transport, Item
7374
from sentry_sdk._log_batcher import LogBatcher
7475
from sentry_sdk._metrics_batcher import MetricsBatcher
@@ -227,6 +228,9 @@ def _capture_log(self, log: "Log", scope: "Scope") -> None:
227228
def _capture_metric(self, metric: "Metric", scope: "Scope") -> None:
228229
pass
229230

231+
def _capture_span(self, span: "StreamedSpan", scope: "Scope") -> None:
232+
pass
233+
230234
def capture_session(self, *args: "Any", **kwargs: "Any") -> None:
231235
return None
232236

@@ -920,7 +924,7 @@ def capture_event(
920924

921925
def _capture_telemetry(
922926
self,
923-
telemetry: "Optional[Union[Log, Metric]]",
927+
telemetry: "Optional[Union[Log, Metric, StreamedSpan]]",
924928
ty: str,
925929
scope: "Scope",
926930
) -> None:
@@ -947,6 +951,8 @@ def _capture_telemetry(
947951
batcher = self.log_batcher
948952
elif ty == "metric":
949953
batcher = self.metrics_batcher # type: ignore
954+
elif ty == "span":
955+
batcher = self.span_batcher # type: ignore
950956

951957
if batcher is not None:
952958
batcher.add(telemetry) # type: ignore
@@ -957,6 +963,9 @@ def _capture_log(self, log: "Optional[Log]", scope: "Scope") -> None:
957963
def _capture_metric(self, metric: "Optional[Metric]", scope: "Scope") -> None:
958964
self._capture_telemetry(metric, "metric", scope)
959965

966+
def _capture_span(self, span: "Optional[StreamedSpan]", scope: "Scope") -> None:
967+
self._capture_telemetry(span, "span", scope)
968+
960969
def capture_session(
961970
self,
962971
session: "Session",

sentry_sdk/scope.py

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@
2929
from sentry_sdk.tracing_utils import (
3030
Baggage,
3131
has_tracing_enabled,
32+
has_span_streaming_enabled,
3233
normalize_incoming_data,
3334
PropagationContext,
3435
)
36+
from sentry_sdk.traces import StreamedSpan
3537
from sentry_sdk.tracing import (
3638
BAGGAGE_HEADER_NAME,
3739
SENTRY_TRACE_HEADER_NAME,
@@ -1278,6 +1280,17 @@ def _capture_metric(self, metric: "Optional[Metric]") -> None:
12781280

12791281
client._capture_metric(metric, scope=merged_scope)
12801282

1283+
def _capture_span(self, span: "Optional[StreamedSpan]") -> None:
1284+
if span is None:
1285+
return
1286+
1287+
client = self.get_client()
1288+
if not has_span_streaming_enabled(client.options):
1289+
return
1290+
1291+
merged_scope = self._merge_scopes()
1292+
client._capture_span(span, scope=merged_scope)
1293+
12811294
def capture_message(
12821295
self,
12831296
message: str,
@@ -1522,16 +1535,25 @@ def _apply_flags_to_event(
15221535
)
15231536

15241537
def _apply_scope_attributes_to_telemetry(
1525-
self, telemetry: "Union[Log, Metric]"
1538+
self, telemetry: "Union[Log, Metric, StreamedSpan]"
15261539
) -> None:
1540+
# TODO: turn Logs, Metrics into actual classes
1541+
if isinstance(telemetry, dict):
1542+
attributes = telemetry["attributes"]
1543+
else:
1544+
attributes = telemetry._attributes
1545+
15271546
for attribute, value in self._attributes.items():
1528-
if attribute not in telemetry["attributes"]:
1529-
telemetry["attributes"][attribute] = value
1547+
if attribute not in attributes:
1548+
attributes[attribute] = value
15301549

15311550
def _apply_user_attributes_to_telemetry(
1532-
self, telemetry: "Union[Log, Metric]"
1551+
self, telemetry: "Union[Log, Metric, StreamedSpan]"
15331552
) -> None:
1534-
attributes = telemetry["attributes"]
1553+
if isinstance(telemetry, dict):
1554+
attributes = telemetry["attributes"]
1555+
else:
1556+
attributes = telemetry._attributes
15351557

15361558
if not should_send_default_pii() or self._user is None:
15371559
return
@@ -1651,16 +1673,19 @@ def apply_to_event(
16511673
return event
16521674

16531675
@_disable_capture
1654-
def apply_to_telemetry(self, telemetry: "Union[Log, Metric]") -> None:
1676+
def apply_to_telemetry(self, telemetry: "Union[Log, Metric, StreamedSpan]") -> None:
16551677
# Attributes-based events and telemetry go through here (logs, metrics,
16561678
# spansV2)
1657-
trace_context = self.get_trace_context()
1658-
trace_id = trace_context.get("trace_id")
1659-
if telemetry.get("trace_id") is None:
1660-
telemetry["trace_id"] = trace_id or "00000000-0000-0000-0000-000000000000"
1661-
span_id = trace_context.get("span_id")
1662-
if telemetry.get("span_id") is None and span_id:
1663-
telemetry["span_id"] = span_id
1679+
if not isinstance(telemetry, StreamedSpan):
1680+
trace_context = self.get_trace_context()
1681+
trace_id = trace_context.get("trace_id")
1682+
if telemetry.get("trace_id") is None:
1683+
telemetry["trace_id"] = (
1684+
trace_id or "00000000-0000-0000-0000-000000000000"
1685+
)
1686+
span_id = trace_context.get("span_id")
1687+
if telemetry.get("span_id") is None and span_id:
1688+
telemetry["span_id"] = span_id
16641689

16651690
self._apply_scope_attributes_to_telemetry(telemetry)
16661691
self._apply_user_attributes_to_telemetry(telemetry)

sentry_sdk/traces.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@
88
import uuid
99
from typing import TYPE_CHECKING
1010

11+
from sentry_sdk.utils import format_attribute
12+
1113
if TYPE_CHECKING:
1214
from typing import Optional
15+
from sentry_sdk._types import Attributes, AttributeValue
1316

1417

1518
class StreamedSpan:
@@ -22,15 +25,40 @@ class StreamedSpan:
2225
span implementation lives in tracing.Span.
2326
"""
2427

25-
__slots__ = ("_trace_id",)
28+
__slots__ = (
29+
"name",
30+
"_attributes",
31+
"_trace_id",
32+
)
2633

2734
def __init__(
2835
self,
2936
*,
37+
name: str,
38+
attributes: "Optional[Attributes]" = None,
3039
trace_id: "Optional[str]" = None,
3140
):
41+
self.name: str = name
42+
self._attributes: "Attributes" = attributes or {}
43+
3244
self._trace_id = trace_id
3345

46+
def get_attributes(self) -> "Attributes":
47+
return self._attributes
48+
49+
def set_attribute(self, key: str, value: "AttributeValue") -> None:
50+
self._attributes[key] = format_attribute(value)
51+
52+
def set_attributes(self, attributes: "Attributes") -> None:
53+
for key, value in attributes.items():
54+
self.set_attribute(key, value)
55+
56+
def remove_attribute(self, key: str) -> None:
57+
try:
58+
del self._attributes[key]
59+
except KeyError:
60+
pass
61+
3462
@property
3563
def trace_id(self) -> str:
3664
if not self._trace_id:

0 commit comments

Comments
 (0)