Skip to content

Conversation

rtpg
Copy link

@rtpg rtpg commented Oct 15, 2025

Description

Django's ASGI handler cancels tasks that have seen a disconnect. This manifests itself in requests potentially opening an OTel span through the Django middleware but not having process_response run in the existing mode, meaning the use_span (this one) closure + context detach call isn't run.

This results in dreaded "this token was created in a different context" errors, which happen because:

  • a task gets cancelled before the use_span activation gets __exit__'d in get_response
  • the use_span generator instead gets garbage collected after the fact
  • the garbage collection runs the finally clause inside the context management code of use_span
  • this causes a call to detach many miles away from the request context

The current Django Middleware design dates back to supporting "old style" middleware, making this problem hard to solve cleanly. Given Django 1.x is now 5 years out of support, I think it's reasonable to drop Django 1.x support to make context management here clearer, through using the new-style __call__ middleware along with a try/finally block.

Fixes # (issue)

This PR does some cleanup to the middleware to make sure that our context and span cleanup always happen, including when there's an asyncio.CancelledError during process handling. But this PR also drops support for Django 1.x in the process, by expecting this middleware to be called via __call__

(I'll handle doc changes etc if I can get approval on dropping Django 1.x support)

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

  • I added a test into the suite that catches this change
  • Testing "live"

In order to see this "in the wild", I added the following sort of thing to a random Django view:

print("sleeping")
sleep(5)
print("done")

I then ran this app with uvicorn, and made requests. When I saw "sleeping" I would close the browser tabs, cancelling the requests. This would lead to the context error appearing.

Does This PR Require a Core Repo Change?

  • No.

Checklist:

See contributing.md for styleguide, changelog guidelines, and more.

  • Followed the style guidelines of this project
  • Changelogs have been updated
  • Unit tests have been added
  • Documentation has been updated

except ImportError:
from django.urls import Resolver404, resolve

DJANGO_2_0 = django_version >= (2, 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Take a look pyproject.toml instruments and opentelemetry.instrumentation.django.package, when you change supported versions you should also change them

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK I went in and removed references to DJANGO_2_0, updated the pyproject.toml instruments and package files.

@xrmx xrmx moved this to Ready for review in @xrmx's Python PR digest Oct 15, 2025
@rtpg rtpg requested a review from a team as a code owner October 16, 2025 00:49
)
request_start_time = request.META.pop(self._environ_timer_key, None)

if activation and span:
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in the case where this method is run, there's definitely an activation and span, so we don't need this if block anymore

@rtpg
Copy link
Author

rtpg commented Oct 16, 2025

Alright I handled the Django 1.x deprecations across the package, and went ahead and added changelog entries.

If you want for me to squash the commits I can, but it looks like maintainers are the ones managing commit creation based on the git log

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Ready for review

Development

Successfully merging this pull request may close these issues.

2 participants