Skip to content
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
2 changes: 1 addition & 1 deletion sentry_sdk/integrations/opentelemetry/propagator.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def inject(

span_id = trace.format_span_id(current_span_context.span_id)

span_map = SentrySpanProcessor().otel_span_map
span_map = SentrySpanProcessor.otel_span_map
sentry_span = span_map.get(span_id, None)
if not sentry_span:
return
Expand Down
7 changes: 7 additions & 0 deletions sentry_sdk/integrations/opentelemetry/span_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ class SentrySpanProcessor(SpanProcessor):
# The currently open spans. Elements will be discarded after SPAN_MAX_TIME_OPEN_MINUTES
open_spans: "dict[int, set[str]]" = {}

initialized: "bool" = False

def __new__(cls) -> "SentrySpanProcessor":
if not hasattr(cls, "instance"):
cls.instance = super().__new__(cls)
Expand All @@ -91,10 +93,15 @@ def __new__(cls) -> "SentrySpanProcessor":
return cls.instance # type: ignore[misc]

def __init__(self) -> None:
if self.initialized:
return

@add_global_event_processor
def global_event_processor(event: "Event", hint: "Hint") -> "Event":
return link_trace_context_to_error_event(event, self.otel_span_map)

self.initialized = True

def _prune_old_spans(self: "SentrySpanProcessor") -> None:
"""
Prune spans that have been open for too long.
Expand Down
25 changes: 25 additions & 0 deletions tests/integrations/opentelemetry/test_propagator.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
from sentry_sdk.integrations.opentelemetry.integration import (
OpenTelemetryIntegration,
)
from opentelemetry import trace
from sentry_sdk.scope import global_event_processors


import pytest

from unittest import mock
Expand Down Expand Up @@ -298,3 +305,21 @@ def test_inject_sentry_span_baggage():
"baggage",
baggage.serialize(),
)


def test_inject_no_memory_leak():

OpenTelemetryIntegration.setup_once()

tracer = trace.get_tracer(__name__)
propagator = SentryPropagator()

cnt_before = len(global_event_processors)

with tracer.start_as_current_span("bar") as new_span:
context = set_span_in_context(new_span)
carrier = "any_carrier"
propagator.inject(carrier, context)

cnt_after = len(global_event_processors)
assert cnt_after == cnt_before
12 changes: 12 additions & 0 deletions tests/integrations/opentelemetry/test_span_processor.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from sentry_sdk.scope import global_event_processors
import time
from datetime import datetime, timezone
from unittest import mock
Expand Down Expand Up @@ -621,3 +622,14 @@ def test_pruning_old_spans_on_end():
span_processor.on_end(otel_span)
assert sorted(list(span_processor.otel_span_map.keys())) == ["111111111abcdef"]
assert sorted(list(span_processor.open_spans.values())) == [{"111111111abcdef"}]


def test_no_memory_leak():
span_processor_1 = SentrySpanProcessor()
cnt_before = len(global_event_processors)

span_processor_2 = SentrySpanProcessor()

cnt_after = len(global_event_processors)
assert span_processor_1 is span_processor_2
assert cnt_before == cnt_after
Loading