File: timer.py

package info (click to toggle)
python-django-debug-toolbar 1%3A5.2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 1,984 kB
  • sloc: python: 6,880; javascript: 631; makefile: 62; sh: 16
file content (106 lines) | stat: -rw-r--r-- 4,164 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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)