open-telemetry / open-telemetry/opentelemetry-python-contrib
Django Instrumentation: Spans close prematurely for StreamingHttpResponse
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1.1k
- Forks
- 1.1k
- Avg merge
- 4d 15h
- Merged PRs (30d)
- 16
Description
What problem do you want to solve?
The current Django instrumentation uses a Middleware to open and close spans. While this works perfectly for standard HTTP responses, it falls short for StreamingHttpResponse.
Because streaming responses continue to process and send data after the middleware chain has finished executing, the request lifecycle is not properly traced, leading to incomplete or inaccurate span durations.
Describe the solution you'd like
A way to solve this is to hook into the response's close() method, which Django guarantees will be called after the stream finishes. We can wrap the original close method to ensure the span is ended at the very end of the response lifecycle.
This approach would gracefully handle both regular and StreamingHttpResponse objects.
Here is a conceptual implementation:
original_close = response.close
def close_span():
try:
original_close()
finally:
# TODO: End the span here
response.close = close_span
Note: I haven't fully tested this with async responses under ASGI yet, where response.close might be executed via sync_to_async.
Describe alternatives you've considered
Another option would be listening to Django's built-in request_finished signal. However, this signal doesn't always carry the exact context of the specific request/response object as cleanly as wrapping the response itself, and might make correlation trickier in concurrent environments.
Additional Context
No response
Would you like to implement a fix?
Yes
Tip
React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by locating the Django instrumentation middleware and how it currently opens and closes spans for responses. Trace the StreamingHttpResponse lifecycle and the response.close hook, then check behavior for both regular and streaming responses, including the noted ASGI sync-to-async case; done means the span ends after streaming completes.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- django, python
- Domain
- backend, observability-sre
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100