Skip to content

Commit

Permalink
Implement defensive programming techniques for setting spans in Conte…
Browse files Browse the repository at this point in the history
…xtVars

to avoid accidentally trying to merge a None with a tuple of Spans

Related to elastic#2056
  • Loading branch information
duck-nukem committed Dec 16, 2024
1 parent e8f75d4 commit 47a0f5d
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 1 deletion.
2 changes: 1 addition & 1 deletion elasticapm/context/contextvars.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def set_span(self, span: "elasticapm.traces.Span") -> None:
The previously-activated span will be saved to be re-activated later.
"""
spans = self.elasticapm_spans_var.get()
spans: tuple = self.elasticapm_spans_var.get() or ()
self.elasticapm_spans_var.set(spans + (span,))

def unset_span(self, clear_all: bool = False) -> "elasticapm.traces.Span":
Expand Down
12 changes: 12 additions & 0 deletions tests/context/test_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,13 @@

import sys

import mock
import pytest

import elasticapm.context
from elasticapm.context.contextvars import ContextVarsContext
from elasticapm.context.threadlocal import ThreadLocalContext
from elasticapm.traces import Span


def test_execution_context_backing():
Expand Down Expand Up @@ -63,3 +66,12 @@ def test_execution_context_monkeypatched(monkeypatch):

# Should always use ThreadLocalContext when thread local is monkey patched
assert isinstance(execution_context, ThreadLocalContext)


def test_none_spans_should_not_raise_a_type_error_on_set_span():
context = ContextVarsContext()
context.elasticapm_spans_var.set(None)

context.set_span(mock.MagicMock(spec=Span))

assert context.get_span() is not None

0 comments on commit 47a0f5d

Please sign in to comment.