每台主机每张图的rrd文件已经创建好了,并且定时每分钟添加从ZabbixAPI取得的监控数据到rrd文件。接下来就得进行图形展示了,在图形
展示前需要将图形归类,不然请求一台主机的图形后还得扒开海量的监控图寻找相关的应用监控图(如nginx、php、redis等)。
我按要求分了两大类主机硬件类和应用信息类。主机类主要展示主与机器相关的监控图如网络、硬盘、CPU负载、内存等。应用信息大类又细分为Nginx_PHP、MySQL、Redis等。效果如下:
实现这些图形的分类第一步,数据库表的设计models。
from django.db import models, connection # Create your models here. ################################################# class DrawTreeManager(models.Manager): def getclass(self, sql): cursor = connection.cursor() cursor.execute(sql) return cursor.fetchall() class DrawTree(models.Model): classname = models.CharField(max_length=64) hostname = models.CharField(max_length=64) hostid = models.CharField(max_length=8) graphid = models.CharField(max_length=8) graphname = models.CharField(max_length=128) draw = models.CharField(max_length=2) type = models.CharField(max_length=2) objects = DrawTreeManager() def __unicode__(self): return self.hostname ################################################ class DrawGraphsManager(models.Manager): def getdata(self, sql): cursor = connection.cursor() cursor.execute(sql) return cursor.fetchall() class DrawGraphs(models.Model): graphid = models.CharField(max_length=8) itemid = models.CharField(max_length=8) itemname = models.CharField(max_length=128) units = models.CharField(max_length=16, null=True, blank=True) objects = DrawGraphsManager() def __unicode__(self): return self.graphid ################################################# class DrawDefManager(models.Manager): def getdata(self, sql): cursor = connection.cursor() cursor.execute(sql) return cursor.fetchall() class DrawDef(models.Model): graphid = models.CharField(max_length=8) cols = models.CharField(max_length=256, null=True, blank=True) types = models.CharField(max_length=256, null=True, blank=True) objects = DrawDefManager() def __unicode__(self): return self.graphid
DrawGraphs表用来存放每张图的所需的信息图形id(graphid)、每张图形包含的item的id和item的名字(itemid、itemname)。根据一个graphid时能够得到这张图形的所有itemid、itemname、unit(item的计数单位),itemid主要是用来冲rrd文件中取对应DS的数据(rrd文件中的DS名我是用的itemid),itemname主要显示图形下面布告牌最大值、最小值神马的,unit就是Y轴显示的单位了。
DrawTree表主要用来存放图形的层叠导航信息的。遍历所有的图形,根据图形名的关键字将每幅图归档。classname字段存放每组的组名,硬件数据的组名取Zabbix的默认分组,应用数据的分组是我自定义的分组如Nginx_PHP、Redis、MySQL等分组。hostname字段对应主机名、hostid对应主机id、graphname对应图形名、graphid对应图形id,draw对应图形是否显示的标志位(1显示、0不显示),type代表图形的分类(0代表硬件信息、1代表Nginx_PHP、2代表MySQL以此类推)。
DrawDef表用来存放自定义图形显示所需的信息。graphid字段为需要自定义显示图形的图形id,cols代表需要自定义图形的颜色代码每种颜色用分号隔开,types对应需要自定义的绘图方法如线性(LINE1、LINE2、LINE3)、区块(AREA)等。
更新DrawTree与跟新DrawGraphs记录是同时进行的(为了精简代码和逻辑),views相关的代码是这样的:
def zabbixindex(request): if request.method == 'GET': for key in request.GET: value = request.GET[key] break if value == 'check': zbx = Zabbix() groupinfo = zbx.group_get() hostsinfo = zbx.hostsid_get() for host in groupinfo: groupid = host['groupid'] groupname = host['groupname'] hostid = host['hostid'] hostname = '' for i in hostsinfo: if i.values()[0] == hostid: hostname = i.keys()[0] break hostgraphs = zbx.hostgraph_get(hostname) for graph in hostgraphs: graphid = graph['graphid'] graphname = graph['name'] #不存在的图形才更新 #图形展示分类 flag = DrawTree.objects.filter(graphid=graphid) if not flag: #更新zabbixapp_drawtree表 draw = '1' if 'PHP-FPM' in graphname or 'Nginx' in graphname: type = '1' classname = 'Nginx_PHP' elif 'MySQL' in graphname or 'InnoDB' in graphname: type = '2' classname = 'MySQL' elif 'Redis' in graphname: type = '3' classname = 'Redis' elif 'Memcached' in graphname: type = '4' classname = 'Memcached' elif 'MongoDB' in graphname: type = '5' classname = 'MongoDB' else: classname = groupname type = '0' DrawTree.objects.create(classname=classname, hostname=hostname, hostid=hostid, graphid=graphid, graphname=graphname, draw=draw, type=type) #更新zabbixapp_drawgraphs表 itemsinfo = zbx.graphitems_get(graphid) units = itemsinfo[0]['units'] for item in itemsinfo: itemid = item['itemid'] itemname = item['name'] DrawGraphs.objects.create(graphid=graphid, itemid=itemid, itemname=itemname, units=units) return HttpResponseRedirect("/graph/zabbix/") #非get或post请求部分,tree ######################## sql_0 = "select distinct classname from zabbixapp_drawtree where type='0'" type_0 = DrawTree.objects.getclass(sql_0) typelist0 = [] for i in type_0: sql = "select distinct hostname,hostid from zabbixapp_drawtree where classname="+"'"+i[0]+"'"+" and type='0'" chosts = DrawTree.objects.getclass(sql) tmplist = [] for chost in chosts: tmp = {'hostname':chost[0], 'hostid':chost[1]} tmplist.append(tmp) typelist0.append({'type':i[0].replace(" ",'-'), 'host':tmplist}) ######################## sql_1 = "select distinct classname from zabbixapp_drawtree where type!='0'" type_1 = DrawTree.objects.getclass(sql_1) typelist1 = [] for i in type_1: sql = "select distinct hostname,hostid,type from zabbixapp_drawtree where classname="+"'"+i[0]+"'" chosts = DrawTree.objects.getclass(sql) tmplist = [] for chost in chosts: tmp = {'hostname':chost[0], 'hostid':chost[1]} tmplist.append(tmp) typelist1.append({'type':i[0], 'host':tmplist, 'tflag': chost[2]}) #value = typelist1 avg = {'privatetitle': 'Zabbix监控数据展示', 'STATIC_URL': '/static', 'list0':typelist0, 'list1':typelist1} return render_to_response('zabbixapp/zabbixindex.html', avg)
该视图函数渲染的模板zabbixindex.html写的比较简单,代码是这样的:
{% extends "base.html" %} {% block title %}{{ privatetitle }}{% endblock %} {% block thercss %} {% endblock %} {% block otherjs %} {% endblock %} {% block content %} <div class="container"> <div class="row"> <div class="col-md-3"> <button type="button" class="btn btn-primary active"> <span class="glyphicon glyphicon-tasks"></span> 硬件数据 </button> {% for i in list0 %} <div> <a href="#{{i.type}}" data-toggle="collapse"><i class="glyphicon glyphicon-hdd"></i>{{i.type}}</a> <ul id="{{i.type}}" class="collapse"> {% for tmp in i.host %} <li><a target="draw" href="/graph/zbdraw/?type=0&hostid={{tmp.hostid}}">{{tmp.hostname}}</a></li> {% endfor %} </ul> </div> {% endfor %} <button type="button" class="btn btn-primary active"> <span class="glyphicon glyphicon-folder-open"></span> 应用数据 </button> {% for i in list1 %} <div> <a href="#{{i.type}}" data-toggle="collapse"><i class="glyphicon glyphicon-usd"></i>{{i.type}}</a> <ul id="{{i.type}}" class="collapse"> {% for tmp in i.host %} <li><a target="draw" href="/graph/zbdraw/?type={{i.tflag}}&hostid={{tmp.hostid}}">{{tmp.hostname}}</a></li> {% endfor %} </ul> </div> {% endfor %} <p></p> <div align="left"> <a href="/graph/zabbix/?action=check" class="btn btn-info" role="button">新增图形检测</a> </div> </div> <script type="text/javascript"> //iframe高度自适应 function autoHeight(){ var iframe = document.getElementById("draw"); if(iframe.Document){//ie自有属性 iframe.style.height = iframe.Document.documentElement.scrollHeight; }else if(iframe.contentDocument){//ie,firefox,chrome,opera,safari iframe.height = iframe.contentDocument.body.offsetHeight ; } } </script> <div class="col-md-9"> <iframe name="draw" id="draw" frameborder="0" scrolling="no" style="width:99%;border:none" onload="autoHeight();"></iframe> </div> </div> </div> {% endblock %}
从ZabbixAPI取图形的各种属性值,经过适当的分类操作后将分类数据在本地落地,然后取落地后的分类数据将硬件和业务信息分类展示出来。