django-commons / django-debug-toolbar

A configurable set of panels that display various debug information about the current request/response.
https://django-debug-toolbar.readthedocs.io
BSD 3-Clause "New" or "Revised" License
8.08k stars 1.05k forks source link

History sidebar panel keeps loading infinitely? #1961

Closed karolyi closed 3 months ago

karolyi commented 3 months ago

Hey,

not sure what I'm mistaking here, but as I open the history panel (without using daphne so it can be turned on), I get endless requests upon trying to open thw history panel:

[09/Jul/2024 20:03:01] "GET /__debug__/history_sidebar/?store_id=665facf9fc8043268809c407f26c9239 HTTP/1.1" 200 10752
[09/Jul/2024 20:03:01] "GET /__debug__/history_sidebar/?store_id=ce761655224342c5a2ee91f81ba1d6a0 HTTP/1.1" 200 10691
[09/Jul/2024 20:03:02] "GET /__debug__/history_sidebar/?store_id=7064e973b5434229a62c5e7e05f99c4f HTTP/1.1" 200 10691
[09/Jul/2024 20:03:02] "GET /__debug__/history_sidebar/?store_id=2dc12ca23eec4949bd50bada5c9aa21d HTTP/1.1" 200 10691
[09/Jul/2024 20:03:02] "GET /__debug__/history_sidebar/?store_id=95ea6042de90411a9a9475f860e24e60 HTTP/1.1" 200 10691
[09/Jul/2024 20:03:03] "GET /__debug__/history_sidebar/?store_id=459c1020581f48bbb01cccd6ec83d53e HTTP/1.1" 200 10691
[09/Jul/2024 20:03:03] "GET /__debug__/history_sidebar/?store_id=243033191ce542dcb8ef39ea3cfd58b3 HTTP/1.1" 200 10693
[09/Jul/2024 20:03:03] "GET /__debug__/history_sidebar/?store_id=8729ff48831942adab47caa2d3d747cc HTTP/1.1" 200 10691
[09/Jul/2024 20:03:03] "GET /__debug__/history_sidebar/?store_id=43841f09a4cf4821824ea9f1e990b749 HTTP/1.1" 200 10691
[09/Jul/2024 20:03:04] "GET /__debug__/history_sidebar/?store_id=52787c0bb5704a9ea86ae6612e92a53c HTTP/1.1" 200 10691
[09/Jul/2024 20:03:04] "GET /__debug__/history_sidebar/?store_id=090b9eab8c5a4e09b614b45eb81652f1 HTTP/1.1" 200 10691
[09/Jul/2024 20:03:04] "GET /__debug__/history_sidebar/?store_id=c471d653bf054895af20625207e4adf9 HTTP/1.1" 200 10691
[09/Jul/2024 20:03:04] "GET /__debug__/history_sidebar/?store_id=c4a770548a6347bdae27f0c880c2cb15 HTTP/1.1" 200 10691
[09/Jul/2024 20:03:05] "GET /__debug__/history_sidebar/?store_id=ac146df811cb46a691f0ed646bc44df2 HTTP/1.1" 200 10691
[09/Jul/2024 20:03:05] "GET /__debug__/history_sidebar/?store_id=464f724930df458f87f83aad07a3f231 HTTP/1.1" 200 10691

It is about 3 requests/sec and I have no idea if that is alright or where to configure it to emit less requests. Normally I would prefer that it only gets the request history when I open the panel, but I couldn't find such an option. It is super hard to find information for the request I really need because what I see is this:

image

Any help here?

tim-schilling commented 3 months ago

You'll need to provide more information. I can see you're using Django 4.2.14.

Please provide:

I suspect what's happening is that the history panel isn't recognizing the request to the toolbar view as an toolbar request, then includes it in the history panel, which then causes it to refresh by making another request.

karolyi commented 3 months ago

Hey,

normally I don't use any extra stuff with the toolbar, but I've ensured that I update to the latest version to make sure it's not something that's already fixed. So,

django-debug-toolbar==4.4.5

The only extra I use in the toolbar settings is: {'TOOLBAR_LANGUAGE': 'en-us'}

No extra JS settings, but the project is pretty huge. I've tested with multiple sub-pages, even pretty simple ones to make sure nothing interferes, but this bug seems to be reproducible everywhere.

tim-schilling commented 3 months ago

Sorry @karolyi, I can't reproduce this. You'll need to do some more legwork to identify why the toolbar isn't integrating well with your project. From there we can decide if it's something with the toolbar that needs to change or the integration itself.

karolyi commented 3 months ago

I figured.

Can you please at least give me a hint about where to find how the toolbar recognizes if a request is a history panel request or not, so it wouldn't fire another request for getting the info of it?

tim-schilling commented 3 months ago

DebugToolbar.is_toolbar_request is the method.

karolyi commented 3 months ago

Thanks.

Will look into it and touch base later. I need some time which I'm really in short supply of, nowadays.

karolyi commented 3 months ago

So, I've found the culprit.

Originally, I used to add the debug URLs to urlpatterns with:

 if settings.DEBUG:
     # Add debug toolbar
    from debug_toolbar import urls as debug_urls
    urlpatterns += [re_path(route=r'^__debug__/', view=include(
        debug_urls, namespace='debug_toolbar'))]

This must have been the old way of adding debug toolbar urls, and must have changed somewhere along the way.

Since the function you mentioned checks for APP_NAME in the url, which isn't debug_toolbar anymore, the recognition of internal debug toolbar URLs has been failing.

Upon updating to the 'new' method of adding debug toolbar URLs, normality has been restored.

tim-schilling commented 3 months ago

I'm glad you figured out the issue. Thank you for following up with the solution! If others run into this, please comment. For now we're not going to make a change (I think).

dmartin commented 3 months ago

I am still seeing the same issue unfortunately, even when using the urlpatterns = [...] + debug_toolbar_urls() pattern.

Possibly interesting factors are that I use the debug toolbar for a JSON API, so I never open it on the actual page I'm inspecting. Rather, I open it on a Django admin panel view, and use the History panel exclusively. Also, I use Django's FORCE_SCRIPT_NAME setting to account for a reverse proxy (my routes are reached under an /api/ path prefix). Finally, I just set "SHOW_TOOLBAR_CALLBACK": lambda _: DEBUG, as the automatic Docker IP detection does not work for me and I don't find the INTERNAL_IPS allowlist worth the hassle.

Basically, after opening the History panel and refreshing it once, it keeps sending requests infinitely as described in the original issue. The only workaround I've found is to set something like: "OBSERVE_REQUEST_CALLBACK": lambda request: "__debug__" not in request.path but that raises a warning since the setting is deprecated.

tim-schilling commented 3 months ago

What are the full relative paths for the toolbar view requests?

tim-schilling commented 3 months ago

It seems like DebugToolbar.is_toolbar_request() may not be matching when it should.

karolyi commented 3 months ago

@dmartin, I figured out the error by putting debugging information into DebugToolbar.is_toolbar_request.

That way, you would have an idea as to why it isn't recognized as a debug toolbar view.

dmartin commented 3 months ago

Yeah, I think I was able to narrow it down to https://github.com/jazzband/django-debug-toolbar/commit/68039c6833410a8f27ccd0d5b574c14c2cb792e8. is_toolbar_request() is working properly, it's just not getting checked anymore for history panel refresh requests since that commit.

That change was made based on the idea that the toolbar never introspects its own requests, but that has not been the case for me, even on 4.3 before this issue began, e.g:

Screenshot 2024-07-22 at 11 54 38 AM

I wonder if it has to do with the odd FORCE_SCRIPT_NAME stuff I'm doing.

dmartin commented 3 months ago

Oops, put some print statements in is_toolbar_request() and I guess the real underlying issue is that Resolver404 is always raised on every request, causing it to return False instead of matching on the namespace.

Edit: Aha, if I patch is_toolbar_request() such that:

from django.urls import get_script_prefix

resolver_match = request.resolver_match or resolve(
    request.path.replace(get_script_prefix(), "/"), getattr(request, "urlconf", None)
)

then everything works as expected. This is similar to https://code.djangoproject.com/ticket/31724. Would a PR like the above be accepted to make the toolbar work with FORCE_SCRIPT_NAME out of the box?