debug_toolbar工作原理

#toolbar的中间件的响应处理函数,会调用到panel.generate_stats(request, response)
def process_response(self, request, response):
toolbar = self.__class__.debug_toolbars.pop(threading.current_thread().ident, None)
if not toolbar:#DebugToolbar对象,每请求对应一个,它可以存储各panel的数据
return response # Run process_response methods of panels like Django middleware.
for panel in reversed(toolbar.enabled_panels):
new_response = panel.process_response(request, response)
if new_response:
response = new_response # Deactivate instrumentation ie. monkey-unpatch. This must run
# regardless of the response. Keep 'return' clauses below.
# (NB: Django's model for middleware doesn't guarantee anything.)
for panel in reversed(toolbar.enabled_panels):#禁止调试模板
panel.disable_instrumentation() # Check for responses where the toolbar can't be inserted.
content_encoding = response.get('Content-Encoding', '')
content_type = response.get('Content-Type', '').split(';')[0]
if any((getattr(response, 'streaming', False),
'gzip' in content_encoding,
content_type not in _HTML_TYPES)):
return response # Collapse the toolbar by default if SHOW_COLLAPSED is set.
if toolbar.config['SHOW_COLLAPSED'] and 'djdt' not in request.COOKIES:
response.set_cookie('djdt', 'hide', 864000) # Insert the toolbar in the response.
content = force_text(response.content, encoding=settings.DEFAULT_CHARSET)
insert_before = dt_settings.CONFIG['INSERT_BEFORE']#'/body'
try: # Python >= 2.7
pattern = re.escape(insert_before)
bits = re.split(pattern, content, flags=re.IGNORECASE)
except TypeError: # Python < 2.7
pattern = '(.+?)(%s|$)' % re.escape(insert_before)
matches = re.findall(pattern, content, flags=re.DOTALL | re.IGNORECASE)
bits = [m[0] for m in matches if m[1] == insert_before]
# When the body ends with a newline, there's two trailing groups.
bits.append(''.join(m[0] for m in matches if m[1] == ''))
if len(bits) > 1:
# When the toolbar will be inserted for sure, generate the stats.
for panel in reversed(toolbar.enabled_panels):
panel.generate_stats(request, response)#调用panel生成统计数据 bits[-2] += toolbar.render_toolbar()#bits[-2]为倒数第二个,即/body前面的内容
response.content = insert_before.join(bits)
if response.get('Content-Length', None):
response['Content-Length'] = len(response.content)
return response

timerpanel时间统计的面板:

def generate_stats(self, request, response):
stats = {}
if hasattr(self, '_start_time'):
stats['total_time'] = (time.time() - 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)#调用记录统计函数。
#panel的记录函数
def record_stats(self, stats):
"""
Store data gathered by the panel. ``stats`` is a :class:`dict`. Each call to ``record_stats`` updates the statistics dictionary.
"""
self.toolbar.stats.setdefault(self.panel_id, {}).update(stats)#更新后,每个请求后的数据统计
上一篇:类ArrayList


下一篇:[C# 网络编程系列]专题十:实现简单的邮件收发器