open-telemetry / open-telemetry/opentelemetry-python-contrib

Django Instrumentation: Spans close prematurely for StreamingHttpResponse

Open
#4,681 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feature-request
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.