-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add .prof File Download Support to Profiling Panel #2146
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
I’ve started working on the enhancement Download profiling results (Issue #1798) and have implemented the backend and template changes to support .prof file download. However, I’m currently getting the following error: django.urls.exceptions.NoReverseMatch: Reverse for 'debug_toolbar_download_prof_file' not found. I’ve defined the download_prof_file view in views.py, but I suspect the issue might be with how I registered it in urls.py or the namespace being used by the toolbar. Since this involves integrating a custom view into the debug toolbar's internal URLs, I’ve kept the PR in draft so you could please review my approach and suggest how I can resolve this. Thank you! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain more what we can do with the .prof
file?
Also, I wonder if we shouldn't just write profile files always to a configured path (in the settings) and not make this a part of the interface? (Not saying that's a better idea, just thinking out loud.)
@@ -168,8 +169,13 @@ def generate_stats(self, request, response): | |||
self.stats = Stats(self.profiler) | |||
self.stats.calc_callees() | |||
|
|||
root_func = cProfile.label(super().process_request.__code__) | |||
prof_file_path = os.path.join( | |||
tempfile.gettempdir(), next(tempfile._get_candidate_names()) + ".prof" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_get_candidate_names()
isn't documented? I think we should only enable this feature when users provide a path where we can store profiles, because we have to ensure we're only serving files from this very path and not arbitrary files.
try: | ||
return self.db.ops.last_executed_query(self.cursor, sql, sample_params) | ||
except Exception: | ||
return sql |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like an unrelated change?
@@ -1,4 +1,13 @@ | |||
{% load i18n %} | |||
|
|||
{% if prof_file_path %} | |||
<div style="margin-bottom: 10px;"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do not have any inline styles in templates until now, if we need styles add them to the toolbar.css
file.
debug_toolbar_views.download_prof_file, | ||
name="debug_toolbar_download_prof_file", | ||
), | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should add the URL pattern to get_urls()
, not here.
|
||
{% if prof_file_path %} | ||
<div style="margin-bottom: 10px;"> | ||
<a href="{% url 'debug_toolbar_download_prof_file' %}?path={{ prof_file_path|urlencode }}" class="djDebugButton"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The toolbar uses the djdt:
namespace for URLs; search the code base for reverse(
calls to see how that can be used. (See git grep -C3 'reverse('
)
def download_prof_file(request): | ||
file_path = request.GET.get("path") | ||
print("Serving .prof file:", file_path) | ||
if not file_path or not os.path.exists(file_path): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can trivially be exploited by using something like
...?path=/etc/passwd
This view serves arbitrary files which are readable by the webserver process: Either you have to use signing (django.core.signing
, also used in the templates panel) to ensure that paths cannot be tampered with and/or use a known root where you put files, and ensure that you only serve files from this root. This isn't totally straightforward because you have to protect against path traversal attacks.
Description
This PR adds a feature to download the raw .prof file generated by cProfile via the Django Debug Toolbar profiling panel.
Users can now export the profiling results to visualize or analyze them externally.
Status: Draft - encountering a NoReverseMatch error related to debug_toolbar_download_prof_file. Likely an issue with urls.py configuration. Seeking guidance on the correct integration approach.
Fixes #1798
Checklist:
docs/changes.rst
.