Skip to content

Commit 8cf1771

Browse files
author
Luke Maisel
committed
fix: ensures BaseMiddleware always creates a new span instead of returning the current span
Updated _create_observability_span to create a new span with the middleware's parent_span context or current context if needed. Updated BaseMiddleware tests to be more accurate and ensure BaseMiddleware does not end outer spans.
1 parent f6985b6 commit 8cf1771

File tree

3 files changed

+25
-6
lines changed

3 files changed

+25
-6
lines changed

packages/http/httpx/kiota_http/middleware/middleware.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,16 @@ async def send(self, request, transport):
6464
return await self.next.send(request, transport)
6565

6666
def _create_observability_span(self, request, span_name: str) -> trace.Span:
67-
"""Gets the parent_span from the request options and creates a new span.
68-
If no parent_span is found, we try to get the current span."""
67+
"""Gets the parent_span from the request options and creates a new span.
68+
If no parent_span is found in the request, uses the parent_span in the
69+
object. If parent_span is None, current context will be used."""
6970
_span = None
7071
if options := getattr(request, "options", None):
7172
if parent_span := options.get("parent_span", None):
7273
self.parent_span = parent_span
7374
_context = trace.set_span_in_context(parent_span)
7475
_span = tracer.start_span(span_name, _context)
7576
if _span is None:
76-
_span = trace.get_current_span()
77+
_context = trace.set_span_in_context(self.parent_span)
78+
_span = tracer.start_span(span_name, _context)
7779
return _span

packages/http/httpx/tests/conftest.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,11 @@ def mock_no_content_response(sample_headers):
211211
tracer = trace.get_tracer(__name__)
212212

213213

214+
@pytest.fixture
215+
def otel_tracer():
216+
return tracer
217+
218+
214219
@pytest.fixture
215220
def mock_otel_span():
216221
return tracer.start_span("mock")

packages/http/httpx/tests/middleware_tests/test_base_middleware.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,21 @@ def test_next_is_none():
1010
assert middleware.next is None
1111

1212

13-
def test_span_created(request_info):
14-
"""Ensures the current span is returned and the parent_span is not set."""
13+
def test_span_returned(request_info):
14+
"""Ensures a span is returned and the parent_span is not set."""
1515
middleware = BaseMiddleware()
16-
span = middleware._create_observability_span(request_info, "test_span_created")
16+
span = middleware._create_observability_span(request_info, "test_span_returned")
17+
span.end()
1718
assert isinstance(span, trace.Span)
1819
assert middleware.parent_span is None
20+
21+
22+
def test_span_created(request_info, otel_tracer):
23+
"""Ensures the span returned does not end an outer context managed span"""
24+
with otel_tracer.start_as_current_span("outside-span") as outside_span:
25+
before_state = outside_span.is_recording()
26+
middleware = BaseMiddleware()
27+
span = middleware._create_observability_span(request_info, "test_span_created")
28+
span.end()
29+
after_state = outside_span.is_recording()
30+
assert(before_state == after_state)

0 commit comments

Comments
 (0)