使用 pyrrd 收集系统信息

在我们的博客中, 记录了我们在开发过程中所使用的技术和遇到的问题, 希望作为其他开发和设计者的一个学习交流平台.

使用 pyrrd 收集系统信息


上星期, 我们想测试几个WSGI应用的评分, 由于不同的concurrency模式, 使我们很难一一设置并评测. 其中的系统信息也是一项重要的指标, 例如CPU消耗, 内存消耗等信息的收集和图像化. RRDtool是一个广泛使用的测试工具. 我们可以通过pyrrd和subprocess模块对每个WSGI应用进行测试:

    from pyrrd.rrd import DataSource, RRA, RRD
    dss = [
        DataSource(dsName='cpu', dsType='GAUGE', heartbeat=4),
        DataSource(dsName='mem', dsType='GAUGE', heartbeat=4)
    ]
    rras = [RRA(cf='AVERAGE', xff=0.5, steps=1, rows=100)]
    rrd = RRD('/tmp/heartbeat.rrd', ds=dss, rra=rras, step=1)
    rrd.create()

以上代码将会使用CPU和内存实用信息创建/tem/heartbeat.rrd文件. 两者都定义为GAUGE类型. 然后我们定义了round-robin archive(RRA)来储存最多100个数据点. 在代码最后, 我们使用之前的设置, 以每秒的速度保存到RRD文件中. pyrrd模块使用的属于与rrdtool相同, 因此我们可以使用现成的rrdtool知识.

使用subprocess:

    pattern = re.compile('\s+')
    command = '/bin/ps --no-headers -o pcpu,pmem -p %s' % ' '.join(pids)
    while True:
        ps = subprocess.check_output(command, shell=True)
        pcpu = 0.0
        pmem = 0.0
        for line in ps.split('\n'):
            if line.strip():
                cpu, mem = map(float, pattern.split(line.strip()))
                pcpu += cpu
                pmem += mem
        rrd.bufferValue(time.time(), pcpu, pmem)
        rrd.update()
        time.sleep(1)

使用ps命令过滤显示每个pid的%CPU和%MEM使用信息, 然后输出经过处理保存到rrd文件.

请注意, 这不是一个典型的rrdtool使用案例. 通常的使用情形是:

    # -*- coding: utf-8 -*-
    
    from __future__ import (absolute_import, division, print_function,
                            with_statement, unicode_literals)
    import re
    import signal
    import sys
    import time
    import subprocess
    from random import random, randint
    from pyrrd.rrd import DataSource, RRA, RRD

    def usage():
        print('%s rrdfile pid, ...' % __file__)
        print('sample the %cpu and %mem for specified pids, aggregated')


    def sigint_handler(signal, frame):
        print("Sampling finishes: %.2f." % time.time())
        sys.exit(0)


    def main():
        rrd_file = sys.argv[1]
        pids = sys.argv[2:]
        dss = [
            DataSource(dsName='cpu', dsType='GAUGE', heartbeat=4),
            DataSource(dsName='mem', dsType='GAUGE', heartbeat=4)
        ]
        rras = [RRA(cf='AVERAGE', xff=0.5, steps=1, rows=100)]
        rrd = RRD(rrd_file, ds=dss, rra=rras, step=1)
        rrd.create()
        signal.signal(signal.SIGINT, sigint_handler)

        pattern = re.compile('\s+')
        command = '/bin/ps --no-headers -o pcpu,pmem -p %s' % ' '.join(pids)
        print("Executing command: '%s'." % command)

        print("Sampling start: %d, press Ctrl-C to stop sampling ..." % int(time.time()))
        while True:
            ps = subprocess.check_output(command, shell=True)
            pcpu = 0.0
            pmem = 0.0
            for line in ps.split('\n'):
                if line.strip():
                    cpu, mem = map(float, pattern.split(line.strip()))
                    pcpu += cpu
                    pmem += mem
            rrd.bufferValue(time.time(), pcpu, pmem)
            rrd.update()
            time.sleep(1)

        # fetch:
        # rrdtool fetch system.rrd AVERAGE --end=now --start=now-50s

        # graph:
        # rrdtool graph /vagrant/xx.png 
#--start 1401919870
#--end 1401919879
#DEF:cpu=system.rrd:cpu:AVERAGE LINE2:cpu#FF0000
#DEF:mem=system.rrd:mem:AVERAGE LINE:mem#ccff00 if __name__ == "__main__": if len(sys.argv) < 3: usage() sys.exit() main()

原文链接: http://www.weiguda.com/blog/51/