cherrypy.lib.cpstats模块¶
cpstats,用于收集和报告程序统计数据的包。
概述¶
程序运行的统计数据是非常宝贵的监视和调试工具。不幸的是,收集和报告这些关键值通常是临时的。该包旨在增加一个收集统计性能数据的集中场所,一个记录数据的结构,该结构提供将数据外推到更有用的信息中,以及一种向人类调查人员和监测软件提供该数据的方法。让我们更详细地分析每一个问题。
数据收集¶
就像 Python 一样 logging
模块为收集和发送消息提供了一个通用的可导入的工具,性能统计数据将从类似的通用机制中获益,并且可以 not 要求希望收集统计信息的每个包导入第三方模块。因此,我们选择重新使用 logging
通过添加 statistics
反对它。
那 logging.statistics
对象是嵌套的dict。它不是自定义类,因为这样会:
需要库和应用程序导入第三方模块才能参与
抑制外推方法和报告工具的创新,以及
慢一点。
但是,关于dict.的结构有一些规范:
{
+----"SQLAlchemy": {
| "Inserts": 4389745,
| "Inserts per Second":
| lambda s: s["Inserts"] / (time() - s["Start"]),
| C +---"Table Statistics": {
| o | "widgets": {-----------+
N | l | "Rows": 1.3M, | Record
a | l | "Inserts": 400, |
m | e | },---------------------+
e | c | "froobles": {
s | t | "Rows": 7845,
p | i | "Inserts": 0,
a | o | },
c | n +---},
e | "Slow Queries":
| [{"Query": "SELECT * FROM widgets;",
| "Processing Time": 47.840923343,
| },
| ],
+----},
}
这个 logging.statistics
口述有四个级别。最顶层只不过是一组用于引入模块化的名称,通常是沿着包名称的行。例如,如果sqlAlchemy项目想要参与,它可能会填充该项。 logging.statistics['SQLAlchemy']
,其值将是第二层dict,我们称之为“命名空间”。名称空间有助于多个包避免键名冲突,并使报表更易于读取和引导。如果需要,sqlAlchemy的维护人员应该可以自由地使用多个命名空间(例如“sqlAlchemy orm”)。请注意,命名空间名称上没有大小写或其他语法约束;它们应该被人类选择为可读性最高(既不太短也不太长)。
然后,每个名称空间都是命名统计值的dict,例如“requests/sec”或“uptime”。您应该选择在报表上看起来不错的名称:空格和大写字母都可以。
除了scalars之外,名称空间中的值可以是(第三层)dict,也可以是名为“collection”的列表。例如,樱桃 StatsTool
跟踪“请求”集合中每个请求正在执行(或最近完成)的操作,其中每个键都是线程ID;子集合中的每个值都必须是第四个dict(whew!)每个线程的统计数据。我们将集合中的每个子集合称为“记录”。同样地, StatsTool
还保留一个慢速查询列表,其中每个记录依次包含有关每个慢速查询的数据。
名称空间或记录中的值也可以是函数,这使我们能够:
外推¶
统计数据的收集需要很快,尽可能接近于宿主程序无法察觉的数据。例如,这要求我们最小化I/O,但在Python中,这也意味着我们需要最小化函数调用。因此,在设计名称空间和记录值时,请尝试插入现有的最基本的标量值。
然而,到了报告收集到的数据的时候,我们通常可以更自由地进行计算。因此,每当报告工具(如提供的 StatsPage
cherrypy类)获取 logging.statistics
为了报告,他们首先打电话 extrapolate_statistics
(通过整个 statistics
听写是唯一的论点)。这会对统计数据dict进行深度复制,以便报告工具可以对其进行迭代,甚至可以在不损害原始数据的情况下对其进行更改。但它也通过调用dict中的任何函数来扩展它们。例如,您可能在命名空间中有一个值为“lambda scope:time.time()”的“当前时间”条目。“scope”参数是当前的名称空间dict(或者record,如果我们现在扩展其中一个名称空间dict),允许您访问现有的静态条目。如果你真的很邪恶,你甚至可以一次修改多个条目。
但是,不要试图计算一个条目,然后在进一步的外推中使用它的值;不能保证函数调用的顺序。这可能导致一定数量的重复工作(或者重新设计模式),但这比使规范复杂化要好。
在整个事情被推断出来之后,是时候:
报告¶
这个 StatsPage
班级抓住 logging.statistics
听写,全部外推,然后将其转换为HTML以便于查看。每个名称空间都有自己的头和属性表,并为每个集合添加一个额外的表。这不是统计规范的一部分;其他工具可以根据自己的喜好进行格式化。
您可以通过更新statspage.formatting来控制输出哪些列以及如何对它们进行格式化,这是一个反映键和嵌套的dict。 logging.statistics
.区别在于,它没有数据值,而是有格式化值。对给定的键使用none向statspage指示不应输出给定的列。使用带格式的字符串(如“%.3f”)插入值,或使用可调用字符串(如lambda v:v.isoformat())进行更高级的格式设置。格式化dict中未提到的任何条目的输出都保持不变。
监测¶
虽然HTML输出很难用统计数据为每个<td>分配唯一的ID,但最好是提取/cpstats/data,它输出整个(外推的)。 logging.statistics
json格式的dict。这可能更容易解析,并且没有任何格式控件,因此您可以以一致的序列化格式获得“原始”数据。注意:目前还没有针对日期时间对象的处理方法。如果可以,现在就尝试time.time()。Nagios可能会感谢你。
关闭收藏¶
建议每个命名空间都有一个“已启用”项,如果为false,则停止收集(但不报告)统计数据。应用程序应通过将这些条目设置为false或true(如果存在)来提供暂停和恢复收集的控件。
使用¶
要收集Cherrypy应用程序的统计信息,请执行以下操作:
from cherrypy.lib import cpstats
appconfig['/']['tools.cpstats.on'] = True
要根据您自己的代码收集统计信息,请执行以下操作:
import logging
# Initialize the repository
if not hasattr(logging, 'statistics'): logging.statistics = {}
# Initialize my namespace
mystats = logging.statistics.setdefault('My Stuff', {})
# Initialize my namespace's scalars and collections
mystats.update({
'Enabled': True,
'Start Time': time.time(),
'Important Events': 0,
'Events/Second': lambda s: (
(s['Important Events'] / (time.time() - s['Start Time']))),
})
...
for event in events:
...
# Collect stats
if mystats.get('Enabled', False):
mystats['Important Events'] += 1
要报告统计信息:
root.cpstats = cpstats.StatsPage()
设置统计报告格式:
See 'Reporting', above.
- class cherrypy.lib.cpstats.StatsPage[源代码]¶
基类:
object
- formatting = {'CherryPy Applications': {'Bytes Read/Request': '%.3f', 'Bytes Read/Second': '%.3f', 'Bytes Written/Request': '%.3f', 'Bytes Written/Second': '%.3f', 'Current Time': <function iso_format>, 'Enabled': <function pause_resume.<locals>._pause_resume>, 'Requests': {'Bytes Read': '%s', 'Bytes Written': '%s', 'End Time': None, 'Processing Time': '%.3f', 'Start Time': None}, 'Requests/Second': '%.3f', 'Slow Queries': {'End Time': None, 'Processing Time': '%.3f', 'Start Time': <function iso_format>}, 'Start Time': <function iso_format>, 'Total Time': '%.3f', 'URI Set Tracking': {'Avg': '%.3f', 'Max': '%.3f', 'Min': '%.3f', 'Sum': '%.3f'}, 'Uptime': '%.3f'}, 'CherryPy WSGIServer': {'Connections/second': '%.3f', 'Enabled': <function pause_resume.<locals>._pause_resume>, 'Start time': <function iso_format>}}¶