Skip to content

Record number of dropped spans in POTel #4092

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Mar 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions sentry_sdk/integrations/opentelemetry/span_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def __init__(self):
self._children_spans = defaultdict(
list
) # type: DefaultDict[int, List[ReadableSpan]]
self._dropped_spans = defaultdict(lambda: 0) # type: DefaultDict[int, int]

def on_start(self, span, parent_context=None):
# type: (Span, Optional[Context]) -> None
Expand Down Expand Up @@ -143,12 +144,17 @@ def _flush_root_span(self, span):
if not transaction_event:
return

collected_spans, dropped_spans = self._collect_children(span)
spans = []
for child in self._collect_children(span):
for child in collected_spans:
span_json = self._span_to_json(child)
if span_json:
spans.append(span_json)

transaction_event["spans"] = spans
if dropped_spans > 0:
transaction_event["_dropped_spans"] = dropped_spans

# TODO-neel-potel sort and cutoff max spans

sentry_sdk.capture_event(transaction_event)
Expand All @@ -166,25 +172,29 @@ def _append_child_span(self, span):
children_spans = self._children_spans[span.parent.span_id]
if len(children_spans) < max_spans:
children_spans.append(span)
else:
self._dropped_spans[span.parent.span_id] += 1

def _collect_children(self, span):
# type: (ReadableSpan) -> List[ReadableSpan]
# type: (ReadableSpan) -> tuple[List[ReadableSpan], int]
if not span.context:
return []
return [], 0

children = []
dropped_spans = 0
bfs_queue = deque() # type: Deque[int]
bfs_queue.append(span.context.span_id)

while bfs_queue:
parent_span_id = bfs_queue.popleft()
node_children = self._children_spans.pop(parent_span_id, [])
dropped_spans += self._dropped_spans.pop(parent_span_id, 0)
children.extend(node_children)
bfs_queue.extend(
[child.context.span_id for child in node_children if child.context]
)

return children
return children, dropped_spans

# we construct the event from scratch here
# and not use the current Transaction class for easier refactoring
Expand Down
5 changes: 2 additions & 3 deletions tests/tracing/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def test_span_trimming(sentry_init, capture_events):

with start_span(name="hi"):
for i in range(10):
with start_span(op="foo{}".format(i)):
with start_span(op=f"foo{i}"):
pass

(event,) = events
Expand All @@ -29,7 +29,6 @@ def test_span_trimming(sentry_init, capture_events):

assert event["_meta"]["spans"][""]["len"] == 10
assert "_dropped_spans" not in event
assert "dropped_spans" not in event


def test_span_data_scrubbing_and_trimming(sentry_init, capture_events):
Expand All @@ -42,7 +41,7 @@ def test_span_data_scrubbing_and_trimming(sentry_init, capture_events):
span.set_data("datafoo", "databar")

for i in range(10):
with start_span(op="foo{}".format(i)):
with start_span(op=f"foo{i}"):
pass

(event,) = events
Expand Down
Loading