Skip to content

Commit 37ced2d

Browse files
Yun-Kimmabdinur
andauthored
chore(asgi): revert regression [backport #5849 to 1.13] (#5851)
Backports #5849 to 1.13. Addresses: #5818 (comment) Partially reverts: #5818 We will need to backport this fix to 1.9, 1.10, 1.11, 1.12 and 1.13 release lines. This regression is unreleased so a release note is not required. ## Checklist - [x] Change(s) are motivated and described in the PR description. - [x] Testing strategy is described if automated tests are not included in the PR. - [x] Risk is outlined (performance impact, potential for breakage, maintainability, etc). - [x] Change is maintainable (easy to change, telemetry, documentation). - [x] [Library release note guidelines](https://ddtrace.readthedocs.io/en/stable/contributing.html#Release-Note-Guidelines) are followed. - [x] Documentation is included (in-code, generated user docs, [public corp docs](https://github.com/DataDog/documentation/)). - [x] OPTIONAL: PR description includes explicit acknowledgement of the performance implications of the change as reported in the benchmarks PR comment. ## Reviewer Checklist - [x] Title is accurate. - [x] No unnecessary changes are introduced. - [x] Description motivates each change. - [x] Avoids breaking [API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces) changes unless absolutely necessary. - [x] Testing strategy adequately addresses listed risk(s). - [x] Change is maintainable (easy to change, telemetry, documentation). - [x] Release note makes sense to a user of the library. - [x] Reviewer has explicitly acknowledged and discussed the performance implications of this PR as reported in the benchmarks PR comment. Co-authored-by: Munir Abdinur <[email protected]>
1 parent bbba41c commit 37ced2d

File tree

4 files changed

+25
-9
lines changed

4 files changed

+25
-9
lines changed

ddtrace/contrib/asgi/middleware.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,20 @@ async def wrapped_send(message):
213213
trace_utils.set_http_meta(
214214
span, self.integration_config, status_code=status_code, response_headers=response_headers
215215
)
216-
return await send(message)
216+
try:
217+
return await send(message)
218+
finally:
219+
# Per asgi spec, "more_body" is used if there is still data to send
220+
# Close the span if "http.response.body" has no more data left to send in the
221+
# response.
222+
if (
223+
message.get("type") == "http.response.body"
224+
and not message.get("more_body", False)
225+
# If the span has an error status code delay finishing the span until the
226+
# traceback and exception message is available
227+
and span.error == 0
228+
):
229+
span.finish()
217230

218231
async def wrapped_blocked_send(message):
219232
accept_header = (
@@ -235,7 +248,11 @@ async def wrapped_blocked_send(message):
235248
message["body"] = bytes(appsec_utils._get_blocked_template(accept_header), "utf-8")
236249
message["more_body"] = False
237250

238-
return await send(message)
251+
try:
252+
return await send(message)
253+
finally:
254+
if message.get("type") == "http.response.body" and span.error == 0:
255+
span.finish()
239256

240257
try:
241258
if _request_blocked(span):

tests/contrib/asgi/test_asgi.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,9 @@ async def tasks_app_with_more_body(scope, receive, send):
127127
await send({"type": "http.response.body", "body": b"*", "more_body": True})
128128
assert not request_span.finished
129129

130-
# assert that the span has not finished after more_body. Span should be finished after
131-
# the ddtrace trace middleware is exited.
130+
# assert that the span has finished after more_body is False
132131
await send({"type": "http.response.body", "body": b"*", "more_body": False})
133-
assert not request_span.finished
132+
assert request_span.finished
134133
await asyncio.sleep(1)
135134

136135

@@ -525,7 +524,7 @@ async def test_tasks_asgi_without_more_body(scope, tracer, test_spans):
525524
assert request_span.span_type == "web"
526525
# typical duration without background task should be in less than 10 ms
527526
# duration with background task will take approximately 1.1s
528-
assert request_span.duration < 1.1
527+
assert request_span.duration < 1
529528

530529

531530
@pytest.mark.asyncio
@@ -548,7 +547,7 @@ async def test_tasks_asgi_with_more_body(scope, tracer, test_spans):
548547
assert request_span.span_type == "web"
549548
# typical duration without background task should be in less than 10 ms
550549
# duration with background task will take approximately 1.1s
551-
assert request_span.duration < 1.1
550+
assert request_span.duration < 1
552551

553552

554553
@pytest.mark.asyncio

tests/contrib/fastapi/test_fastapi.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,7 @@ def test_background_task(client, tracer, test_spans):
629629
assert request_span.resource == "GET /asynctask"
630630
# typical duration without background task should be in less than 10 ms
631631
# duration with background task will take approximately 1.1s
632-
assert request_span.duration < 1.1
632+
assert request_span.duration < 1
633633

634634

635635
@pytest.mark.parametrize("host", ["hostserver", "hostserver:5454"])

tests/contrib/starlette/test_starlette.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,4 +534,4 @@ def test_background_task(client, tracer, test_spans):
534534
assert request_span.resource == "GET /backgroundtask"
535535
# typical duration without background task should be in less than 10ms
536536
# duration with background task will take approximately 1.1s
537-
assert request_span.duration < 1.1
537+
assert request_span.duration < 1

0 commit comments

Comments
 (0)