下面來給各位介紹一個Zabbix與RRDtool繪圖篇之用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命名,這樣做就能正確的找到數據源了.
解決了這些邏輯上的麻煩后,就可以堆繪圖代碼了,首先根據GET請求的hostid和type找到要進行繪圖的rrd文件,rrdtooldraw02,處理這個GET請求的views的函數是這樣的:
- 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}) --Vevb.com
- 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圖形.
貼上真正的繪圖函數,繪制一個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的圖形需要繪圖,貌似我是想不到更好的方法了,只得慢慢細心的堆代碼了,如果想到更優秀的方法,請告訴我一下,謝謝.
|
新聞熱點
疑難解答