Skip to content

6.0.0

Choose a tag to compare

@juanmitaboada juanmitaboada released this 14 Oct 12:10
· 16 commits to master since this release
v6.0.0
d2ddb27
  • pyinstrument is gated like the debug toolbar. With DEBUG_PYINSTRUMENT, autoload() installs codenerix.debug_middleware.ProfilerMiddleware, a subclass of pyinstrument's middleware that only profiles requests accepted by the new codenerix.debug.show_pyinstrument (a project PYINSTRUMENT_SHOW_CALLBACK, if set, still applies on top). Before, pyinstrument.middleware.ProfilerMiddleware was appended to MIDDLEWARE, behind the page cache: any client could get a profile with ?profile, and the profile page was cached and served to everyone asking for that URL, even with a restrictive PYINSTRUMENT_SHOW_CALLBACK. The profile page is sent with Cache-Control: no-store. Projects that list pyinstrument's own middleware in MIDDLEWARE keep it where it is; the gate then applies only if they set PYINSTRUMENT_SHOW_CALLBACK = "codenerix.debug.show_pyinstrument". - Debug requests (those codenerix.debug.is_debug_request() accepts) bypass Django's page cache: they are never served from it and never stored in it, and their responses carry Cache-Control: no-store. When it installs a debug tool, autoload() replaces django.middleware.cache.UpdateCacheMiddleware, FetchFromCacheMiddleware and CacheMiddleware in MIDDLEWARE with the codenerix.debug_middleware subclasses of the same name, which behave as Django's for every other request. This closes two leaks the 5.3.3 placement left open with the toolbar on: the toolbar's own endpoints (__debug__/render_panel/ and the like) were cacheable and then served to any client asking for the same URL, and instrumented responses carried Cache-Control: max-age=600. Toolbar captures are also always cache misses now. - The superuser check works for middlewares placed before SessionMiddleware and AuthenticationMiddleware, where every debug middleware sits since 5.3.3. Without request.user, the gate reads the user from the session cookie, read-only: a session whose hash only verifies against SECRET_KEY_FALLBACKS is rejected rather than rotated, so the gate never logs the request out. In 5.3.3 the superuser check silently failed closed at that position.

  • One set of settings drives every debug tool (toolbar, debug_panel and pyinstrument), read per request by codenerix.debug.is_debug_request():

    • DEBUG_ALLOWED_IPS replaces DEBUG_TOOLBAR_ALLOWED_IPS. When it is not defined, nobody sees the debug tools: INTERNAL_IPS and upstream's default callback no longer apply. "0.0.0.0" still means any client (constant renamed to codenerix.debug.DEBUG_ANY_IP).
    • DEBUG_REQUIRE_SUPERUSER replaces DEBUG_TOOLBAR_REQUIRE_SUPERUSER and defaults to True with DEBUG on or off (it defaulted to not DEBUG). A development setup that should show the tools without logging in must set it to False.
    • autoload(..., DEBUG_PRODUCTION=False) replaces DEBUG_TOOLBAR_PRODUCTION, and now also enables pyinstrument with DEBUG=False. The old keyword raises TypeError.
    • The removed settings are not read as aliases: if any of them is still defined, system check codenerix.E001 reports it and every debug tool stays off.
  • With DEBUG=False, "0.0.0.0" in DEBUG_ALLOWED_IPS requires DEBUG_REQUIRE_SUPERUSER = True; without a login, production needs an explicit list of client IPs. Same rule as before, under the new names.

  • autoload() places pyinstrument's middleware like the toolbar's: at the start of MIDDLEWARE or right after GZipMiddleware, outside the toolbar ([profiler, toolbar, ...]). Projects with DEBUG=True and DEBUG_PYINSTRUMENT=True see it move from the end of MIDDLEWARE to the start, and it now needs DEBUG_ALLOWED_IPS (and a superuser login, by default) to profile anything.

  • The toolbar stands aside on requests carrying pyinstrument's URL argument (PYINSTRUMENT_URL_ARGUMENT, profile by default) when a profiler middleware is in MIDDLEWARE: the profile replaces the response, so the two never run on the same request and the toolbar's cost stays out of the profile. With PYINSTRUMENT_PROFILE_DIR (every request profiled to disk), requests without that argument still run the toolbar, and its cost is in those profiles.

  • codenerix.debug.debug_toolbar_access_errors is now debug_access_errors, and the system check function codenerix.checks.check_debug_toolbar_access is now check_debug_access. The check id stays codenerix.E001. It now also reports a profiler middleware placed behind the page cache, stock page cache middlewares left in MIDDLEWARE next to a debug tool (for instance when the project adds them after calling autoload()), and a toolbar middleware whose DEBUG_TOOLBAR_CONFIG["SHOW_TOOLBAR_CALLBACK"] is not codenerix.debug.show_toolbar (upstream's callback ignores DEBUG_ALLOWED_IPS). The tool concerned fails closed on its own placement errors; a misplaced profiler does not switch the toolbar off, nor the other way round. Like any Error, these stop runserver and migrate.