Zabbix与RRDtool绘图篇(5)_用RRDtool绘制图形

前言

RRDtool在python里面的绘图函数是rrdtool.graph(),函数的各个参数代表什么意义就不讲了,主要讲思路,后面贴上绘图函数的代码就会明白了。在成千上万的监控图的海洋里怎样用最短和最通用的方法将这些图片绘出了是个问题。我目前由于水平的限制能够想到的解决问题的方法是这样的。

  1. 所有的图形都有有限的item,将相同数目item的图片用同一个函数来绘制。
  2. 一些特别的图形如内存堆栈图(stack),可以在该函数中写个判断语句单独配置相应的绘图参数。
  3. 关于item的颜色和绘制方式(LINE1,LINE2,AREA),需要特别照顾的图形可以在DrawDef这张表中定义,其它的图形的item就采用自动默认就好。
  4. 成千上万的item绘图时怎样真确的找到rrd文件中对应的DS,取得正确的数据。这个一开始就设计好了,每台主机的所有rrd文件放在一个文件夹里,文件夹以主机id命名,每个rrd文件以图形id命名并带上.rrd的后缀,每个rrd文件的DS用itemid命名。这样做就能正确的找到数据源了。
    解决了这些逻辑上的麻烦后,就可以堆绘图代码了。
定位rrd文件

首先根据GET请求的hostid和type找到要进行绘图的rrd文件
rrdtooldraw02
处理这个GET请求的view函数:

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
def zabbixdraw(request): 
dir = r"/opt/rrd/"
pngdir = r"/opt/www/diewu/static/images/rrdpng/"
#value = request.GET
hostid = request.GET['hostid']
type = request.GET['type']
sql = "select hostid, graphid, graphname, hostname from zabbixapp_drawtree where hostid="+hostid+" and type="+type+" and draw='1'"
graphs = DrawTree.objects.getclass(sql)
pngs = []
gdatas = []
strtime = str(int(time.time()- 86400))
for graph in graphs:
hostid = graph[0]
graphid = graph[1]
graphname = graph[2]
hostname = graph[3]
rpath = dir + hostid + r"/" + graphid + r".rrd"
if not os.path.exists(pngdir + hostid + r"/"):
os.makedirs(pngdir + hostid + r"/")
pngname = pngdir + hostid + r"/" + graphid + r".png"
sql = "select itemid,itemname,units from zabbixapp_drawgraphs where graphid="+graphid
pitem = DrawGraphs.objects.getdata(sql)
#####取自定义颜色和绘制方法
sql = "select cols from zabbixapp_drawdef where graphid="+graphid
cols = DrawDef.objects.getdata(sql)
if cols:
cols = (cols[0][0].split(":"),)
sql = "select types from zabbixapp_drawdef where graphid="+graphid
itypes = DrawDef.objects.getdata(sql)
if itypes:
itypes = (itypes[0][0].split(":"),)
gdata = {'pname':pngname, 'gname':graphname, 'rrdpath':rpath, 'pitem':pitem, 'graphid':graphid, 'cols':cols, 'itypes':itypes, 'host':hostname, 'stime':strtime, 'flag':'Daily'}
gdatas.append(gdata)
pngs.append({'pngpath':str(pngname).replace(r"/opt/www/diewu", ''), 'graphid':graphid}
drawrrd.drawmain(gdatas)
#value = gdatas
#avg = {'privatetitle': 'Zabbix监控数据展示', 'STATIC_URL': '/static', 'value':value, 'pngs':pngs}
avg = {'privatetitle': 'Zabbix监控数据展示', 'STATIC_URL': '/static', 'pngs':pngs}
return render_to_response('zabbixapp/zabbixdraw.html', avg)

其中自定义的绘图函数drawrrd.drawmain()函数主要是用来遍历需要绘制的图形,根据图形数据提供的item个数,再调用相应的绘图函数绘制出对应的png图形。

根据rrd文件绘图

drawrrd.py 绘制一个item图形的和绘制2个item的图形的函数。

#!/usr/bin/env python 
#coding=utf-8 
import rrdtool 

def dItem01(data): 
  pngname = str(data['pname']) 
  start = data['stime'] 
  graphname = str(data['gname'] + " (" + data['graphid'] + ") " + data['host'] + "(" + data['flag'] + ")") 
  DEF = str(r"DEF:a="+data['rrdpath']+r':'+data['pitem'][0][0]+r":AVERAGE") 
  if data['cols'] or data['itypes']: 
    if not data['cols']: 
      dtype = str(data['itypes'][0][0]+r":a#EAAF00FF:"+data['pitem'][0][1]) 
    elif not data['itypes']: 
      dtype = str(r"AREA:a"+data['cols'][0][0]+r":"+data['pitem'][0][1]) 
    else: 
      dtype = str(data['itypes'][0][0]+r":a"+data['cols'][0][0]+r":"+data['pitem'][0][1]) 
  else: 
    dtype = str(r"AREA:a#EAAF00FF:"+data['pitem'][0][1]) 
  unit = str(data['pitem'][0][2]) 
  if not unit: 
    unit = ' ' 
  max = 'GPRINT:a:MAX:Max\:%.2lf %s' 
  min = 'GPRINT:a:MIN:Min\:%.2lf %s' 
  avg = 'GPRINT:a:AVERAGE:Avg\:%.2lf %s' 
  now = 'GPRINT:a:LAST:Now\:%.2lf %s' 
  rrdtool.graph(pngname, '-w', '600', '-h', '144', '-l', '0', '-s', start, 
                '-t', graphname, '-v', unit, DEF, 'COMMENT: \\n', dtype, now, 
                avg, min, max, 'COMMENT: \\n') 


def dItem02(data): 
  pngname = str(data['pname']) 
  start = data['stime'] 
  graphname = str(data['gname'] + " (" + data['graphid'] + ") " + data['host'] + "(" + data['flag'] + ")") 
  DEFa = str(r"DEF:a="+data['rrdpath']+r':'+data['pitem'][0][0]+r":AVERAGE") 
  DEFb = str(r"DEF:b="+data['rrdpath']+r':'+data['pitem'][1][0]+r":AVERAGE") 
  unit = str(data['pitem'][0][2]) 
  if not unit: 
    unit = ' ' 
  if data['cols'] or data['itypes']: 
    if not data['cols']: 
      dtypea = str(data['itypes'][0][0]+r":a#00CF00FF:"+data['pitem'][0][1]) 
      dtypeb = str(data['itypes'][0][1]+r":b#002A97FF:"+data['pitem'][1][1]) 
    elif not data['itypes']: 
      dtypea = str(r"AREA:a"+data['cols'][0][0]+r":"+data['pitem'][0][1]) 
      dtypeb = str(r"LINE1:b"+data['cols'][0][1]+r":"+data['pitem'][1][1]) 
    else: 
      dtypea = str(data['itypes'][0][0]+r":a"+data['cols'][0][0]+r":"+data['pitem'][0][1]) 
      dtypeb = str(data['itypes'][0][1]+r":b"+data['cols'][0][1]+r":"+data['pitem'][1][1]) 
  else: 
    dtypea = str(r"AREA:a#00CF00FF:"+data['pitem'][0][1]) 
    dtypeb = str(r"LINE1:b#002A97FF:"+data['pitem'][1][1]) 
  maxa = 'GPRINT:a:MAX:Max\:%.2lf %s' 
  mina = 'GPRINT:a:MIN:Min\:%.2lf %s' 
  avga = 'GPRINT:a:AVERAGE:Avg\:%.2lf %s' 
  nowa = 'GPRINT:a:LAST:Now\:%.2lf %s' 
  maxb = 'GPRINT:b:MAX:Max\:%.2lf %s' 
  minb = 'GPRINT:b:MIN:Min\:%.2lf %s' 
  avgb = 'GPRINT:b:AVERAGE:Avg\:%.2lf %s' 
  nowb = 'GPRINT:b:LAST:Now\:%.2lf %s' 
  rrdtool.graph(pngname, '-w', '600', '-h', '144', '-l', '0', '-s', start, '-t', 
                graphname, '-v', unit, DEFa, DEFb, 'COMMENT: \\n', dtypea, nowa, 
                avga, mina, maxa, 'COMMENT: \\n', dtypeb, nowb, avgb, minb, maxb, 
                'COMMENT: \\n')

如果有24个item的图形需要绘图,貌似我是想不到更好的方法了,只得慢慢细心的堆代码了。

----------------本文结束 感谢阅读----------------