Skip to content

Commit 47a0f5d

Browse files
committed
Implement defensive programming techniques for setting spans in ContextVars
to avoid accidentally trying to merge a None with a tuple of Spans Related to #2056
1 parent e8f75d4 commit 47a0f5d

File tree

2 files changed

+13
-1
lines changed

2 files changed

+13
-1
lines changed

elasticapm/context/contextvars.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def set_span(self, span: "elasticapm.traces.Span") -> None:
7878
7979
The previously-activated span will be saved to be re-activated later.
8080
"""
81-
spans = self.elasticapm_spans_var.get()
81+
spans: tuple = self.elasticapm_spans_var.get() or ()
8282
self.elasticapm_spans_var.set(spans + (span,))
8383

8484
def unset_span(self, clear_all: bool = False) -> "elasticapm.traces.Span":

tests/context/test_context.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,13 @@
3030

3131
import sys
3232

33+
import mock
3334
import pytest
3435

3536
import elasticapm.context
37+
from elasticapm.context.contextvars import ContextVarsContext
3638
from elasticapm.context.threadlocal import ThreadLocalContext
39+
from elasticapm.traces import Span
3740

3841

3942
def test_execution_context_backing():
@@ -63,3 +66,12 @@ def test_execution_context_monkeypatched(monkeypatch):
6366

6467
# Should always use ThreadLocalContext when thread local is monkey patched
6568
assert isinstance(execution_context, ThreadLocalContext)
69+
70+
71+
def test_none_spans_should_not_raise_a_type_error_on_set_span():
72+
context = ContextVarsContext()
73+
context.elasticapm_spans_var.set(None)
74+
75+
context.set_span(mock.MagicMock(spec=Span))
76+
77+
assert context.get_span() is not None

0 commit comments

Comments
 (0)