def graph(rrd, back=86400, title="", width=400, height=100): """ Make an RRD graph. The caller is responsible for deleting the returned path """ tfile, tpath = tempfile.mkstemp(".gif", "oh") os.close(tfile) RRD.graph( tpath, "--start", "-" + str(back), "--title", title, "-w", str(width), "-h", str(height), "-c", "SHADEB#FFFFFF", "-c", "SHADEA#FFFFFF", "DEF:in=%s:in:AVERAGE" % rrd, "DEF:out=%s:out:AVERAGE" % rrd, "CDEF:inbits=in,8,*", "CDEF:outbits=out,8,*", 'AREA:inbits#00FF00:"bps in"', 'LINE1:outbits#0000FF:"bps out"', ) return tpath
def _create_rrd(server): path = os.path.join(cfg.VAR_DB_OPENVPS, 'vsmon', '%s.rrd' % server) args = [path, '-s', '60'] for n in xrange(len(cfg.VSMON_DATA_DEF)): field = cfg.VSMON_DATA_DEF[n] if field[1]: args.append( _DS(field[0][:19], dst=field[1], hbeat=field[2], min=field[3], max=field[4])) # here due to the billing policy we will probably need to keep 40 # days of 1 minute samples. at the end of 30 days they should be # transferred to a real database... although - what can't it be # transferred on daily basis? args.append(_RRA('AVERAGE', xff=0.5, steps=1, rows=14400)) # 10 days of 1 min args.append(_RRA('AVERAGE', xff=0.5, steps=10, rows=13392)) # 93 days of 5 min args.append(_RRA('AVERAGE', xff=0.5, steps=43200, rows=120)) # 10 years of 30 days #log(`args`) RRD.create(args)
def graph(rrd, back=86400, title='', width=400, height=100): """ Make an RRD graph. The caller is responsible for deleting the returned path """ tfile, tpath = tempfile.mkstemp('.gif', 'oh') os.close(tfile) RRD.graph(tpath, '--start', '-' + str(back), '--title', title, '-w', str(width), '-h', str(height), '-c', 'SHADEB#FFFFFF', '-c', 'SHADEA#FFFFFF', 'DEF:in=%s:in:AVERAGE' % rrd, 'DEF:out=%s:out:AVERAGE' % rrd, 'CDEF:inbits=in,8,*', 'CDEF:outbits=out,8,*', 'AREA:inbits#00FF00:"bps in"', 'LINE1:outbits#0000FF:"bps out"') return tpath
def report_sum(name, start=None, end=None): # fetch data from our RRD's rrdargs = [ os.path.join(cfg.VAR_DB_OPENVPS, 'vsmon', name + '.rrd'), 'AVERAGE' ] if start: rrdargs.append('--start') rrdargs.append(start) if end: rrdargs.append('--end') rrdargs.append(end) header, rows = RRD.fetch(*rrdargs) step = int(rows[1][0] - rows[0][0]) result = { 'start': rows[0][0], 'end': rows[-1][0], 'step': step, 'steps': len(rows), 'ticks': 0, 'vm': 0, 'rss': 0, 'in': 0, 'out': 0, 'disk': 0, } for row in rows: ticks = _sum_none(header, row, ['vs_uticks', 'vs_sticks']) result['ticks'] += ticks result['vm'] += _sum_none(header, row, ['vs_vm']) result['rss'] += _sum_none(header, row, ['vs_rss']) result['in'] += _sum_none(header, row, ['vs_in']) result['out'] += _sum_none(header, row, ['vs_out']) result['disk'] += _sum_none(header, row, ['vs_disk_b_used']) # a COUNTER is always per-second. To get the actual number, it # is AVG * STEP (where step is in seconds) # a GAUGE is an average (i.e. not per-second). If our tokens are # based on a per-minute interval, then the total tokens would be # sum(averages) * (STEP/60) result['ticks'] = result['ticks'] * step # counter result['vm'] = result['vm'] * (step / 60) # gauge result['rss'] = result['rss'] * (step / 60) # gauge result['in'] = result['in'] * step # counter result['out'] = result['out'] * step # counter result['disk'] = result['disk'] * (step / 60) # gauge return result
def report_sum(name, start=None, end=None): # fetch data from our RRD's rrdargs = [os.path.join(cfg.VAR_DB_OPENVPS, "vsmon", name + ".rrd"), "AVERAGE"] if start: rrdargs.append("--start") rrdargs.append(start) if end: rrdargs.append("--end") rrdargs.append(end) header, rows = RRD.fetch(*rrdargs) step = int(rows[1][0] - rows[0][0]) result = { "start": rows[0][0], "end": rows[-1][0], "step": step, "steps": len(rows), "ticks": 0, "vm": 0, "rss": 0, "in": 0, "out": 0, "disk": 0, } for row in rows: ticks = _sum_none(header, row, ["vs_uticks", "vs_sticks"]) result["ticks"] += ticks result["vm"] += _sum_none(header, row, ["vs_vm"]) result["rss"] += _sum_none(header, row, ["vs_rss"]) result["in"] += _sum_none(header, row, ["vs_in"]) result["out"] += _sum_none(header, row, ["vs_out"]) result["disk"] += _sum_none(header, row, ["vs_disk_b_used"]) # a COUNTER is always per-second. To get the actual number, it # is AVG * STEP (where step is in seconds) # a GAUGE is an average (i.e. not per-second). If our tokens are # based on a per-minute interval, then the total tokens would be # sum(averages) * (STEP/60) result["ticks"] = result["ticks"] * step # counter result["vm"] = result["vm"] * (step / 60) # gauge result["rss"] = result["rss"] * (step / 60) # gauge result["in"] = result["in"] * step # counter result["out"] = result["out"] * step # counter result["disk"] = result["disk"] * (step / 60) # gauge return result
def update_rrd(server, data): if not _rrd_exists(server): _create_rrd(server) # template tmpl = [] for k in cfg.VSMON_DATA_DEF: if k[1]: tmpl.append(k[0][:19]) vals = ['N'] for k in cfg.VSMON_DATA_DEF: if k[1]: vals.append('%s' % data[k[0]]) path = os.path.join(cfg.VAR_DB_OPENVPS, 'vsmon', '%s.rrd' % server) args = [path, '-t'] + [':'.join(tmpl)] + [':'.join(vals)] #log(`args`) RRD.update(args)
def update_rrd(server, data): if not _rrd_exists(server): _create_rrd(server) # template tmpl = [] for k in cfg.VSMON_DATA_DEF: if k[1]: tmpl.append(k[0][:19]) vals = ["N"] for k in cfg.VSMON_DATA_DEF: if k[1]: vals.append("%s" % data[k[0]]) path = os.path.join(cfg.VAR_DB_OPENVPS, "vsmon", "%s.rrd" % server) args = [path, "-t"] + [":".join(tmpl)] + [":".join(vals)] # log(`args`) RRD.update(args)
def _create_rrd(server): path = os.path.join(cfg.VAR_DB_OPENVPS, "vsmon", "%s.rrd" % server) args = [path, "-s", "60"] for n in xrange(len(cfg.VSMON_DATA_DEF)): field = cfg.VSMON_DATA_DEF[n] if field[1]: args.append(_DS(field[0][:19], dst=field[1], hbeat=field[2], min=field[3], max=field[4])) # here due to the billing policy we will probably need to keep 40 # days of 1 minute samples. at the end of 30 days they should be # transferred to a real database... although - what can't it be # transferred on daily basis? args.append(_RRA("AVERAGE", xff=0.5, steps=1, rows=14400)) # 10 days of 1 min args.append(_RRA("AVERAGE", xff=0.5, steps=10, rows=13392)) # 93 days of 5 min args.append(_RRA("AVERAGE", xff=0.5, steps=43200, rows=120)) # 10 years of 30 days # log(`args`) RRD.create(args)
def period_total(rrd, start, end, dslist=['in', 'out']): start, end = int(float(start)), int(float(end)) header, rows = RRD.fetch(rrd, 'AVERAGE', '-s', str(start), '-e', str(end)) step = rows[1][0] - rows[0][0] # convert DS names to numeric indecies dslist = [list(header).index(x) for x in dslist] totals = [0] * len(dslist) for row in rows: n = 0 for ds_idx in dslist: if row[ds_idx]: totals[n] += row[ds_idx] n += 1 return step, totals
def period_total(rrd, start, end, dslist=["in", "out"]): start, end = int(float(start)), int(float(end)) header, rows = RRD.fetch(rrd, "AVERAGE", "-s", str(start), "-e", str(end)) step = rows[1][0] - rows[0][0] # convert DS names to numeric indecies dslist = [list(header).index(x) for x in dslist] totals = [0] * len(dslist) for row in rows: n = 0 for ds_idx in dslist: if row[ds_idx]: totals[n] += row[ds_idx] n += 1 return step, totals
def uptime(req, s='-2592000'): # 30 days args = ['/dev/null', '--start', s, '--width=500'] # bizzare, but we need --width to match rrds = _list_server_rrds() # list of rrds, each like # 'DEF:s0=/var/db/openvps/iad01-06-04-01.openvps.net-uptime.rrd:admin_uptime:AVERAGE', for n in xrange(len(rrds)): args.append('DEF:s%d=%s:admin_uptime:AVERAGE' % (n, rrds[n])) # now the tricky part - construct sum in RPN #'CDEF:avg=s0,s1,+,s2,+,s3,+,s4,+,s5,+,s6,+,s7,+,8,/', rpn = ['s0'] for n in xrange(1, len(rrds)): rpn.append('s%d' % n) rpn.append('+') rpn.append('%d' % len(rrds)) rpn.append('/') args.append('CDEF:avg=' + (','.join(rpn))) # the average args.append('VDEF:tot_avg=avg,AVERAGE') # the output args.append('PRINT:tot_avg:"average uptime\\: %9.6lf"') uptime = RRD.graph(*args)[2][0][1:-1] #req.log_error(`args`) return uptime
def disk(req, name, params): if params.startswith('graph'): if not req.args: return error(req, 'Not sure what you mean') qargs = util.parse_qs(req.args) if not qargs.has_key('s'): return error(req, 'Where do I start?') start = '-'+qargs['s'][0] width = 484 height = 70 nolegend = '' if qargs.has_key('l'): nolegend = '-g' # no legend # how many days back? secs = abs(int(start)) if secs < 60*60*24: # we're talking hours title = 'last %d hours' % (secs/(60*60)) else: title = 'last %d days' % (secs/(60*60*24)) rrd = os.path.join(cfg.VAR_DB_OPENVPS, 'vsmon/%s.rrd' % name) tfile, tpath = tempfile.mkstemp('.gif', 'oh') os.close(tfile) args = [tpath, '--start', start, '--title', title, '-w', str(width), '-h', str(height), '-c', 'SHADEB#FFFFFF', '-c', 'SHADEA#FFFFFF', '-l', '0', 'DEF:d=%s:vs_disk_b_used:AVERAGE' % rrd, 'CDEF:db=d,1024,*', 'AREA:db#4eee94:bytes used'] if qargs.has_key('l'): args.append('-g') # no legend RRD.graph(*args) req.content_type = 'image/gif' req.sendfile(tpath) os.unlink(tpath) return apache.OK else: location = 'stats:disk' body_tmpl = _tmpl_path('disk_body.html') rrd = os.path.join(cfg.VAR_DB_OPENVPS, 'vsmon/%s.rrd' % name) data = _load_rrd_data(rrd, ['vs_disk_b_used']) body_vars = {'data':data} vars = {'global_menu': _global_menu(req, name, location), 'body':psp.PSP(req, body_tmpl, vars=body_vars), 'name':name} p = psp.PSP(req, _tmpl_path('main_frame.html'), vars=vars) p.run() return apache.OK
def graph(req, name, command): if not req.args: return error(req, 'Not sure what you mean') qargs = util.parse_qs(req.args) if not qargs.has_key('s'): return error(req, 'Where do I start?') start = '-'+qargs['s'][0] # exclude these vps's exclude = [] if qargs.has_key('exclude'): exclude = qargs['exclude'][0].split() # limit to only these vps's limit = [] if qargs.has_key('limit'): limit = qargs['limit'][0].split() width = 600 if qargs.has_key('w'): width = int(qargs['w'][0]) height = 400 if qargs.has_key('h'): height = int(qargs['h'][0]) # how many days back? secs = abs(int(start)) if secs < 60*60*24: # we're talking hours title = 'last %d hours' % (secs/(60*60)) else: title = 'last %d days' % (secs/(60*60*24)) if command in ['bwidth', 'mem']: # here we need to draw a nice little graph.... tfile, tpath = tempfile.mkstemp('.gif', 'oh') os.close(tfile) args = [tpath, '--start', start, '--title', title, '-w', str(width), '-h', str(height), '-c', 'SHADEB#FFFFFF', '-c', 'SHADEA#FFFFFF', '-l', '0'] if qargs.has_key('l'): args.append('-g') # no legend # list vservers vservers = vsutil.list_vservers() keys = vservers.keys() # assign colors colors = {} ci = 0 for vs in keys: colors[vs.replace('-', '')] = COLORS[ci] ci += 1 # process limit and exclude if limit: keys = [k for k in keys if k in limit] keys = [k for k in keys if k not in exclude] # we only have so many colors if len(keys) > len(COLORS): return error(req, 'Not enough colors for VPSs, exclude some:\n%s' % `keys`) keys.sort() for vs in keys: rrd = os.path.join(cfg.VAR_DB_OPENVPS, 'vsmon/%s.rrd' % vs) vs = vs.replace('-', '') # rrdtool does not like dashes if command == 'bwidth': args = args + [ 'DEF:%s_in=%s:vs_in:AVERAGE' % (vs, rrd), 'DEF:%s_out=%s:vs_out:AVERAGE' % (vs, rrd), 'CDEF:%s_inb=%s_in,-8,*' % (vs, vs), 'CDEF:%s_outb=%s_out,8,*' % (vs, vs) ] elif command == 'mem': args = args + [ 'DEF:%s_vm=%s:vs_vm:AVERAGE' % (vs, rrd), 'DEF:%s_rss=%s:vs_rss:AVERAGE' % (vs, rrd), 'CDEF:%s_vmb=%s_vm,1024,*' % (vs, vs), 'CDEF:%s_rssb=%s_rss,1024,*' % (vs, vs), 'CDEF:%s_rssbg=%s_rss,-1024,*' % (vs, vs), ] if command == 'bwidth': # incoming vs = keys[0].replace('-', '') args = args + [ 'AREA:%s_outb#%s:%s bps out' % (vs, colors[vs], vs.ljust(10)), 'GPRINT:%s_inb:MAX:Max IN\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_inb:AVERAGE:Avg IN\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_outb:MAX:Max OUT\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_outb:AVERAGE:Avg OUT\\: %%8.2lf%%s\\n' % (vs, ) ] for vs in keys[1:]: vs = vs.replace('-', '') args = args + [ 'STACK:%s_outb#%s:%s bps out' % (vs, colors[vs], vs.ljust(10)), 'GPRINT:%s_inb:MAX:Max IN\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_inb:AVERAGE:Avg IN\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_outb:MAX:Max OUT\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_outb:AVERAGE:Avg OUT\\: %%8.2lf%%s\\n' % (vs, ) ] # outgoing keys.reverse() vs = keys[0].replace('-', '') args = args + [ 'AREA:%s_inb#%s::' % (vs, colors[vs]), ] for vs in keys[1:]: vs = vs.replace('-', '') args = args + [ 'STACK:%s_inb#%s::' % (vs, colors[vs]), ] elif command == 'mem': # rss (displayed at bottom) vs = keys[0].replace('-', '') args = args + [ 'AREA:%s_rssbg#%s:%s RSS bytes' % (vs, colors[vs], vs.ljust(10)), 'GPRINT:%s_rssb:MAX:Max RSS\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_rssb:AVERAGE:Avg RSS\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_vmb:MAX:Max VM\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_vmb:AVERAGE:Avg VM\\: %%8.2lf%%s\\n' % (vs, ) ] for vs in keys[1:]: vs = vs.replace('-', '') args = args + [ 'STACK:%s_rssbg#%s:%s RSS bytes' % (vs, colors[vs], vs.ljust(10)), 'GPRINT:%s_rssb:MAX:Max RSS\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_rssb:AVERAGE:Avg RSS\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_vmb:MAX:Max VM\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_vmb:AVERAGE:Avg VM\\: %%8.2lf%%s\\n' % (vs, ) ] # vm keys.reverse() vs = keys[0].replace('-', '') args = args + [ 'AREA:%s_vmb#%s::' % (vs, colors[vs]), ] for vs in keys[1:]: vs = vs.replace('-', '') args = args + [ 'STACK:%s_vmb#%s::' % (vs, colors[vs]), ] RRD.graph(*args) req.content_type = 'image/gif' req.sendfile(tpath) os.unlink(tpath) return apache.OK else: return error(req, 'request not understood')
def uptime_graph(req, s='-2592000'): # 30 days # generate a temporary path tfile, tpath = tempfile.mkstemp('.png', 'ova') os.close(tfile) args = [tpath, '--start', s, '--imgformat=PNG', '--width=600', '--base=1000', '--height=120', '--interlaced', '--lower-limi', '80', '--upper-limit', '101', '--rigid'] rrds = _list_server_rrds() # list of rrds, each like # 'DEF:s0=/var/db/openvps/iad01-06-04-01.openvps.net-uptime.rrd:admin_uptime:AVERAGE', for n in xrange(len(rrds)): args.append('DEF:s%d=%s:admin_uptime:AVERAGE' % (n, rrds[n])) # now the tricky part - construct sum in RPN #'CDEF:avg=s0,s1,+,s2,+,s3,+,s4,+,s5,+,s6,+,s7,+,8,/', rpn = ['s0'] for n in xrange(1, len(rrds)): rpn.append('s%d' % n) rpn.append('+') rpn.append('%d' % len(rrds)) rpn.append('/') args.append('CDEF:avg=' + (','.join(rpn))) # the average args.append('VDEF:tot_avg=avg,AVERAGE') trend = 60*60*24*7 # 7 days # trended average args.append('CDEF:tavg=avg,%d,TREND' % trend) degr = '99.99' # degraded - anything less than 99.99% args.append('CDEF:degr=avg,%s,GE,0,INF,IF' % degr) # degraded shade args.append('AREA:degr#ffff99:degraded\\n') # tranded average args.append('LINE2:tavg#0000FF:%d day moving average\\n' % (trend / (60*60*24))) # real uptime args.append('LINE:avg#00FF00:simple average\\n') # the output args.append('COMMENT:\\n') args.append('GPRINT:tot_avg:Last %d Day Average\\: %%9.6lf\\n' % (abs(int(s)) / (60*60*24))) # run it RRD.graph(*args) req.content_type = 'image/png' req.sendfile(tpath) os.unlink(tpath) return
def disk(req, name, params): if params.startswith('graph'): if not req.args: return error(req, 'Not sure what you mean') qargs = util.parse_qs(req.args) if not qargs.has_key('s'): return error(req, 'Where do I start?') start = '-' + qargs['s'][0] width = 484 height = 70 nolegend = '' if qargs.has_key('l'): nolegend = '-g' # no legend # how many days back? secs = abs(int(start)) if secs < 60 * 60 * 24: # we're talking hours title = 'last %d hours' % (secs / (60 * 60)) else: title = 'last %d days' % (secs / (60 * 60 * 24)) rrd = os.path.join(cfg.VAR_DB_OPENVPS, 'vsmon/%s.rrd' % name) tfile, tpath = tempfile.mkstemp('.gif', 'oh') os.close(tfile) args = [ tpath, '--start', start, '--title', title, '-w', str(width), '-h', str(height), '-c', 'SHADEB#FFFFFF', '-c', 'SHADEA#FFFFFF', '-l', '0', 'DEF:d=%s:vs_disk_b_used:AVERAGE' % rrd, 'CDEF:db=d,1024,*', 'AREA:db#4eee94:bytes used' ] if qargs.has_key('l'): args.append('-g') # no legend RRD.graph(*args) req.content_type = 'image/gif' req.sendfile(tpath) os.unlink(tpath) return apache.OK else: location = 'stats:disk' body_tmpl = _tmpl_path('disk_body.html') rrd = os.path.join(cfg.VAR_DB_OPENVPS, 'vsmon/%s.rrd' % name) data = _load_rrd_data(rrd, ['vs_disk_b_used']) body_vars = {'data': data} vars = { 'global_menu': _global_menu(req, name, location), 'body': psp.PSP(req, body_tmpl, vars=body_vars), 'name': name } p = psp.PSP(req, _tmpl_path('main_frame.html'), vars=vars) p.run() return apache.OK
def graph(req, name, command): if not req.args: return error(req, 'Not sure what you mean') qargs = util.parse_qs(req.args) if not qargs.has_key('s'): return error(req, 'Where do I start?') start = '-' + qargs['s'][0] # exclude these vps's exclude = [] if qargs.has_key('exclude'): exclude = qargs['exclude'][0].split() # limit to only these vps's limit = [] if qargs.has_key('limit'): limit = qargs['limit'][0].split() width = 600 if qargs.has_key('w'): width = int(qargs['w'][0]) height = 400 if qargs.has_key('h'): height = int(qargs['h'][0]) # how many days back? secs = abs(int(start)) if secs < 60 * 60 * 24: # we're talking hours title = 'last %d hours' % (secs / (60 * 60)) else: title = 'last %d days' % (secs / (60 * 60 * 24)) if command in ['bwidth', 'mem']: # here we need to draw a nice little graph.... tfile, tpath = tempfile.mkstemp('.gif', 'oh') os.close(tfile) args = [ tpath, '--start', start, '--title', title, '-w', str(width), '-h', str(height), '-c', 'SHADEB#FFFFFF', '-c', 'SHADEA#FFFFFF', '-l', '0' ] if qargs.has_key('l'): args.append('-g') # no legend # list vservers vservers = vsutil.list_vservers() keys = vservers.keys() # assign colors colors = {} ci = 0 for vs in keys: colors[vs.replace('-', '')] = COLORS[ci] ci += 1 # process limit and exclude if limit: keys = [k for k in keys if k in limit] keys = [k for k in keys if k not in exclude] # we only have so many colors if len(keys) > len(COLORS): return error( req, 'Not enough colors for VPSs, exclude some:\n%s' % ` keys `) keys.sort() for vs in keys: rrd = os.path.join(cfg.VAR_DB_OPENVPS, 'vsmon/%s.rrd' % vs) vs = vs.replace('-', '') # rrdtool does not like dashes if command == 'bwidth': args = args + [ 'DEF:%s_in=%s:vs_in:AVERAGE' % (vs, rrd), 'DEF:%s_out=%s:vs_out:AVERAGE' % (vs, rrd), 'CDEF:%s_inb=%s_in,-8,*' % (vs, vs), 'CDEF:%s_outb=%s_out,8,*' % (vs, vs) ] elif command == 'mem': args = args + [ 'DEF:%s_vm=%s:vs_vm:AVERAGE' % (vs, rrd), 'DEF:%s_rss=%s:vs_rss:AVERAGE' % (vs, rrd), 'CDEF:%s_vmb=%s_vm,1024,*' % (vs, vs), 'CDEF:%s_rssb=%s_rss,1024,*' % (vs, vs), 'CDEF:%s_rssbg=%s_rss,-1024,*' % (vs, vs), ] if command == 'bwidth': # incoming vs = keys[0].replace('-', '') args = args + [ 'AREA:%s_outb#%s:%s bps out' % (vs, colors[vs], vs.ljust(10)), 'GPRINT:%s_inb:MAX:Max IN\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_inb:AVERAGE:Avg IN\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_outb:MAX:Max OUT\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_outb:AVERAGE:Avg OUT\\: %%8.2lf%%s\\n' % (vs, ) ] for vs in keys[1:]: vs = vs.replace('-', '') args = args + [ 'STACK:%s_outb#%s:%s bps out' % (vs, colors[vs], vs.ljust(10)), 'GPRINT:%s_inb:MAX:Max IN\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_inb:AVERAGE:Avg IN\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_outb:MAX:Max OUT\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_outb:AVERAGE:Avg OUT\\: %%8.2lf%%s\\n' % (vs, ) ] # outgoing keys.reverse() vs = keys[0].replace('-', '') args = args + [ 'AREA:%s_inb#%s::' % (vs, colors[vs]), ] for vs in keys[1:]: vs = vs.replace('-', '') args = args + [ 'STACK:%s_inb#%s::' % (vs, colors[vs]), ] elif command == 'mem': # rss (displayed at bottom) vs = keys[0].replace('-', '') args = args + [ 'AREA:%s_rssbg#%s:%s RSS bytes' % (vs, colors[vs], vs.ljust(10)), 'GPRINT:%s_rssb:MAX:Max RSS\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_rssb:AVERAGE:Avg RSS\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_vmb:MAX:Max VM\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_vmb:AVERAGE:Avg VM\\: %%8.2lf%%s\\n' % (vs, ) ] for vs in keys[1:]: vs = vs.replace('-', '') args = args + [ 'STACK:%s_rssbg#%s:%s RSS bytes' % (vs, colors[vs], vs.ljust(10)), 'GPRINT:%s_rssb:MAX:Max RSS\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_rssb:AVERAGE:Avg RSS\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_vmb:MAX:Max VM\\: %%8.2lf%%s' % (vs, ), 'GPRINT:%s_vmb:AVERAGE:Avg VM\\: %%8.2lf%%s\\n' % (vs, ) ] # vm keys.reverse() vs = keys[0].replace('-', '') args = args + [ 'AREA:%s_vmb#%s::' % (vs, colors[vs]), ] for vs in keys[1:]: vs = vs.replace('-', '') args = args + [ 'STACK:%s_vmb#%s::' % (vs, colors[vs]), ] RRD.graph(*args) req.content_type = 'image/gif' req.sendfile(tpath) os.unlink(tpath) return apache.OK else: return error(req, 'request not understood')