107 lines
4.1 KiB
Python
107 lines
4.1 KiB
Python
|
from time import perf_counter
|
||
|
|
||
|
from django.template.loader import render_to_string
|
||
|
from django.templatetags.static import static
|
||
|
from django.utils.translation import gettext_lazy as _
|
||
|
|
||
|
from debug_toolbar.panels import Panel
|
||
|
|
||
|
try:
|
||
|
import resource # Not available on Win32 systems
|
||
|
except ImportError:
|
||
|
resource = None
|
||
|
|
||
|
|
||
|
class TimerPanel(Panel):
|
||
|
"""
|
||
|
Panel that displays the time a response took in milliseconds.
|
||
|
"""
|
||
|
|
||
|
def nav_subtitle(self):
|
||
|
stats = self.get_stats()
|
||
|
if hasattr(self, "_start_rusage"):
|
||
|
utime = self._end_rusage.ru_utime - self._start_rusage.ru_utime
|
||
|
stime = self._end_rusage.ru_stime - self._start_rusage.ru_stime
|
||
|
return _("CPU: %(cum)0.2fms (%(total)0.2fms)") % {
|
||
|
"cum": (utime + stime) * 1000.0,
|
||
|
"total": stats["total_time"],
|
||
|
}
|
||
|
elif "total_time" in stats:
|
||
|
return _("Total: %0.2fms") % stats["total_time"]
|
||
|
else:
|
||
|
return ""
|
||
|
|
||
|
has_content = resource is not None
|
||
|
|
||
|
title = _("Time")
|
||
|
|
||
|
template = "debug_toolbar/panels/timer.html"
|
||
|
|
||
|
@property
|
||
|
def content(self):
|
||
|
stats = self.get_stats()
|
||
|
rows = (
|
||
|
(_("User CPU time"), _("%(utime)0.3f msec") % stats),
|
||
|
(_("System CPU time"), _("%(stime)0.3f msec") % stats),
|
||
|
(_("Total CPU time"), _("%(total)0.3f msec") % stats),
|
||
|
(_("Elapsed time"), _("%(total_time)0.3f msec") % stats),
|
||
|
(
|
||
|
_("Context switches"),
|
||
|
_("%(vcsw)d voluntary, %(ivcsw)d involuntary") % stats,
|
||
|
),
|
||
|
)
|
||
|
return render_to_string(self.template, {"rows": rows})
|
||
|
|
||
|
@property
|
||
|
def scripts(self):
|
||
|
scripts = super().scripts
|
||
|
scripts.append(static("debug_toolbar/js/timer.js"))
|
||
|
return scripts
|
||
|
|
||
|
def process_request(self, request):
|
||
|
self._start_time = perf_counter()
|
||
|
if self.has_content:
|
||
|
self._start_rusage = resource.getrusage(resource.RUSAGE_SELF)
|
||
|
return super().process_request(request)
|
||
|
|
||
|
def generate_stats(self, request, response):
|
||
|
stats = {}
|
||
|
if hasattr(self, "_start_time"):
|
||
|
stats["total_time"] = (perf_counter() - self._start_time) * 1000
|
||
|
if hasattr(self, "_start_rusage"):
|
||
|
self._end_rusage = resource.getrusage(resource.RUSAGE_SELF)
|
||
|
stats["utime"] = 1000 * self._elapsed_ru("ru_utime")
|
||
|
stats["stime"] = 1000 * self._elapsed_ru("ru_stime")
|
||
|
stats["total"] = stats["utime"] + stats["stime"]
|
||
|
stats["vcsw"] = self._elapsed_ru("ru_nvcsw")
|
||
|
stats["ivcsw"] = self._elapsed_ru("ru_nivcsw")
|
||
|
stats["minflt"] = self._elapsed_ru("ru_minflt")
|
||
|
stats["majflt"] = self._elapsed_ru("ru_majflt")
|
||
|
# these are documented as not meaningful under Linux. If you're
|
||
|
# running BSD feel free to enable them, and add any others that I
|
||
|
# hadn't gotten to before I noticed that I was getting nothing but
|
||
|
# zeroes and that the docs agreed. :-(
|
||
|
#
|
||
|
# stats['blkin'] = self._elapsed_ru('ru_inblock')
|
||
|
# stats['blkout'] = self._elapsed_ru('ru_oublock')
|
||
|
# stats['swap'] = self._elapsed_ru('ru_nswap')
|
||
|
# stats['rss'] = self._end_rusage.ru_maxrss
|
||
|
# stats['srss'] = self._end_rusage.ru_ixrss
|
||
|
# stats['urss'] = self._end_rusage.ru_idrss
|
||
|
# stats['usrss'] = self._end_rusage.ru_isrss
|
||
|
|
||
|
self.record_stats(stats)
|
||
|
|
||
|
def generate_server_timing(self, request, response):
|
||
|
stats = self.get_stats()
|
||
|
|
||
|
self.record_server_timing("utime", "User CPU time", stats.get("utime", 0))
|
||
|
self.record_server_timing("stime", "System CPU time", stats.get("stime", 0))
|
||
|
self.record_server_timing("total", "Total CPU time", stats.get("total", 0))
|
||
|
self.record_server_timing(
|
||
|
"total_time", "Elapsed time", stats.get("total_time", 0)
|
||
|
)
|
||
|
|
||
|
def _elapsed_ru(self, name):
|
||
|
return getattr(self._end_rusage, name) - getattr(self._start_rusage, name)
|