有几个朋友一直问我,页面的实时监控咋做。
他们在做idc节点的监控,我推荐用smokeping和zabbix接口的方式测试。但那哥们挺执着的,非要好看点的图表~
关于运维业务的实时监控,我做过两套方案:
第一种是用websocket的方式,这个时效性最强,也最快最及时。第二套用的是节点自己插入数据库,或者是通过接口插入到数据库,然后页面通过刷新来取出数据库里面的值,来渲染页面。。。。
这两个都有点开发比较麻烦,维护也麻烦。。。正好我这段时间在搞saltstack,一直想利用mq的速度来做小型的监控方案。。。
下面的小例子,就可以实现。。。。
我们先用cmd.run实现下,再用grains采集信息。。。
先放出一个小demo~
原文地址:http://rfyiamcool.blog.51cto.com/1030776/1266437
很简单的实现过程
1. 通过saltstack modules 和grains 收集信息
2. 然后放到页面中
今天找个时间写出来.
安装flask 然后直接跑就行了~
先简单写了个点击刷新信息页面~
这里缺一个bootstrap的css 需要大家自己引入。。。
放到同一个目录下就行啦~
#!/usr/bin/env python #coding=utf-8 from flask import Flask,url_for,request,render_template,redirect,abort,escape,session from werkzeug import secure_filename import os print __name__ app = Flask(__name__) app.secret_key = 'hello' @app.route('/') def index(): p=os.popen('salt \'*\' grains.item psnum netnum').read() p=os.popen('salt \* cmd.run \'netstat -an|wc -l\'').read() return ''' <!DOCTYPE html> <!-- saved from url=(0053)http://www.bootcss.com/examples/marketing-narrow.html --> <html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta charset="utf-8"> <title>xiaorui.cc</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content=""> <meta name="author" content=""> <!-- Le styles --> <link href="bootstrap.min.css" rel="stylesheet"> <style type="text/css"> body { padding-top: 20px; padding-bottom: 40px; } /* Custom container */ .container-narrow { margin: 0 auto; max-width: 700px; } .container-narrow > hr { margin: 30px 0; } /* Main marketing message and sign up button */ .jumbotron { margin: 60px 0; text-align: center; } .jumbotron h1 { font-size: 72px; line-height: 1; } .jumbotron .btn { font-size: 21px; padding: 14px 24px; } /* Supporting marketing content */ .marketing { margin: 60px 0; } .marketing p + h4 { margin-top: 28px; } </style> <link href="http://cdnjs.bootcss.com/ajax/libs/twitter-bootstrap/2.3.1/css/bootstrap-responsive.min.css" rel="stylesheet"> <!-- HTML5 shim, for IE6-8 support of HTML5 elements --> <!--[if lt IE 9]> <script src="//cdnjs.bootcss.com/ajax/libs/html5shiv/3.6.2/html5shiv.js"></script> <![endif]--> <!-- Fav and touch icons --> <link rel="apple-touch-icon-precomposed" sizes="144x144" href="http://www.bootcss.com/assets/ico/apple-touch-icon-144-precomposed.png"> <link rel="apple-touch-icon-precomposed" sizes="114x114" href="http://www.bootcss.com/assets/ico/apple-touch-icon-114-precomposed.png"> <link rel="apple-touch-icon-precomposed" sizes="72x72" href="http://www.bootcss.com/assets/ico/apple-touch-icon-72-precomposed.png"> <link rel="apple-touch-icon-precomposed" href="http://www.bootcss.com/assets/ico/apple-touch-icon-57-precomposed.png"> <link rel="shortcut icon" href="http://www.bootcss.com/assets/ico/favicon.png"> <script>window["_GOOG_TRANS_EXT_VER"] = "1";</script></head> <body> <div class="container-narrow"> <div class="masthead"> <ul class="nav nav-pills pull-right"> <li class="active"><a href="http://www.bootcss.com/examples/marketing-narrow.html#">Home</a></li> <li><a href="http://www.bootcss.com/examples/marketing-narrow.html#">命令推送</a></li> <li><a href="http://www.bootcss.com/examples/marketing-narrow.html#">图标监控</a></li> </ul> <h3 class="muted">实时监控</h3> </div> <hr> <div class="jumbotron"> <pre>%s</pre> <a class="btn btn-large btn-success" href="http://10.10.10.66:8888">刷新</a> </div> <hr> <hr> <div class="footer"> <h4>by xiaorui.cc</h4> </div> </div> <!-- /container --> <!-- Le javascript ================================================== --> <!-- Placed at the end of the document so the pages load faster --> </body></html> '''%p @app.route('/user/<username>') def show_username(username): return username @app.route('/post/<int:post_id>') def show_post(post_id): return 'post_id:%d' % post_id @app.route('/index/') def test_session(): if 'username' in session: return 'logged in as %s' % escape(session['username']) return redirect(url_for('login')) @app.route('/login/',methods=['GET','POST']) def login(): if request.method == 'POST': session['username'] = request.form['username'] return redirect(url_for('test_session')) else: return ''' <form action="/login/" method="post"> <input type=text name=username> <input type=submit value=login> </form> ''' @app.route('/setcookie') def set_cookie(): if 'num' in request.cookies: count = int(request.cookies['num']) + 1 else: count = 0 response = app.make_response(str(count)) response.set_cookie('num',value=count,max_age=None,expires=None,domain=None) return response if __name__ == "__main__": app.run(host="10.10.10.66",port=8888,debug=True)
xiaorui.cc
花了半小时把图表展现给更新出来,这个只是简单的demo。
让大家体验下 数据填充图表的做法。
后端数据都是静态的,下次再写个动态的渲染。
关于这些业务数据,大家可以把执行结果往库里仍,然后从库里拉出来。可以用saltstack的returners把数据搞到mysql或者mongodb。
或者是放一个全局的变量,把数据往list的最后面放,满12个数值话,开始清除第一个,然后把数据往后放。。。。
或者是把saltstack的执行结果放到文本里面,两个列 一个是时间轴 一个是数据轴。然后搞出来,渲染到前端。
总之,能搞出规律的x轴和y轴就行啦。。。
#!/usr/bin/env python #coding=utf-8 #xiaorui.cc from flask import Flask,url_for,request,render_template,redirect,abort,escape,session from werkzeug import secure_filename import os print __name__ app = Flask(__name__) app.secret_key = 'hello' @app.route('/') def index(): p=os.popen('salt \'*\' grains.item psnum netnum').read() p=os.popen('salt \* cmd.run \'netstat -an|wc -l\'').read() return ''' <!DOCTYPE html> <!-- saved from url=(0053)http://www.bootcss.com/examples/marketing-narrow.html --> <html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta charset="utf-8"> <title>xiaorui.cc</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content=""> <meta name="author" content=""> <!-- Le styles --> <link href="http://cdnjs.bootcss.com/ajax/libs/twitter-bootstrap/2.3.1/css/bootstrap.min.css" rel="stylesheet"> <style type="text/css"> body { padding-top: 20px; padding-bottom: 40px; } /* Custom container */ .container-narrow { margin: 0 auto; max-width: 700px; } .container-narrow > hr { margin: 30px 0; } /* Main marketing message and sign up button */ .jumbotron { margin: 60px 0; text-align: center; } .jumbotron h1 { font-size: 72px; line-height: 1; } .jumbotron .btn { font-size: 21px; padding: 14px 24px; } /* Supporting marketing content */ .marketing { margin: 60px 0; } .marketing p + h4 { margin-top: 28px; } </style> <link href="http://cdnjs.bootcss.com/ajax/libs/twitter-bootstrap/2.3.1/css/bootstrap-responsive.min.css" rel="stylesheet"> <!-- HTML5 shim, for IE6-8 support of HTML5 elements --> <!--[if lt IE 9]> <script src="//cdnjs.bootcss.com/ajax/libs/html5shiv/3.6.2/html5shiv.js"></script> <![endif]--> <!-- Fav and touch icons --> <link rel="apple-touch-icon-precomposed" sizes="144x144" href="http://www.bootcss.com/assets/ico/apple-touch-icon-144-precomposed.png"> <link rel="apple-touch-icon-precomposed" sizes="114x114" href="http://www.bootcss.com/assets/ico/apple-touch-icon-114-precomposed.png"> <link rel="apple-touch-icon-precomposed" sizes="72x72" href="http://www.bootcss.com/assets/ico/apple-touch-icon-72-precomposed.png"> <link rel="apple-touch-icon-precomposed" href="http://www.bootcss.com/assets/ico/apple-touch-icon-57-precomposed.png"> <link rel="shortcut icon" href="http://www.bootcss.com/assets/ico/favicon.png"> <script>window["_GOOG_TRANS_EXT_VER"] = "1";</script></head> <body> <div class="container-narrow"> <div class="masthead"> <ul class="nav nav-pills pull-right"> <li class="active"><a href="http://www.bootcss.com/examples/marketing-narrow.html#">Home</a></li> <li><a href="http://www.bootcss.com/examples/marketing-narrow.html#">命令推送</a></li> <li><a href="http://www.bootcss.com/examples/marketing-narrow.html#">图标监控</a></li> </ul> <h3 class="muted">实时监控</h3> </div> <hr> <div class="jumbotron"> <pre>%s</pre> <a class="btn btn-large btn-success" href="http://10.10.10.66:8888">刷新</a> </div> <hr> <hr> <div class="footer"> <h4>by xiaorui.cc</h4> </div> </div> <!-- /container --> <!-- Le javascript ================================================== --> <!-- Placed at the end of the document so the pages load faster --> </body></html> '''%p @app.route('/charts.html') def show_username(): p=[1,2,3,4,5,6,7,8,9,1,2,3] return ''' <!DOCTYPE html> <!-- saved from url=(0053)http://www.bootcss.com/examples/marketing-narrow.html --> <html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta charset="utf-8"> <title>xiaorui.cc</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content=""> <meta name="author" content=""> <link href="http://67.xiaorui.cc/bootstrap.min.css" rel="stylesheet"> <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.1.min.js"></script> <script type="text/javascript" src="http://67.xiaorui.cc/highcharts.js"></script> <script type="text/javascript" src="http://67.xiaorui.cc/exporting.js"></script> <style type="text/css"> body { padding-top: 20px; padding-bottom: 40px; } /* Custom container */ .container-narrow { margin: 0 auto; max-width: 700px; } .container-narrow > hr { margin: 30px 0; } /* Main marketing message and sign up button */ .jumbotron { margin: 60px 0; text-align: center; } .jumbotron h1 { font-size: 72px; line-height: 1; } .jumbotron .btn { font-size: 21px; padding: 14px 24px; } /* Supporting marketing content */ .marketing { margin: 60px 0; } .marketing p + h4 { margin-top: 28px; } </style> <script type="text/javascript"> var chart; $(document).ready(function() { chart = new Highcharts.Chart({ chart: { renderTo: 'container', defaultSeriesType: 'line', marginRight: 130, marginBottom: 25 }, title: { text: 'netstat 监控', x: -20 //center }, subtitle: { text: '让我们看看连接书哈', x: -20 }, xAxis: { categories: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'] }, yAxis: { title: { text: '连接数' }, plotLines: [{ value: 0, width: 1, color: '#808080' }] }, tooltip: { formatter: function() { return '<b>'+ this.series.name +'</b><br/>'+ this.x +': '+ this.y +'°C'; }, }, legend: { layout: 'vertical', align: 'right', verticalAlign: 'top', x: -10, y: 100, borderWidth: 0 }, series: [{ name: '66.ruifengyun.cc', data: [-0.2, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8, 24.1, 20.1, 14.1, 8.6, 2.5] }, { name: '67.ruifengyun.cc', data: [-0.9, 0.6, 3.5, 8.4, 13.5, 17.0, 18.6, 17.9, 14.3, 9.0, 3.9, 1.0] }, { name: 'ceshi', data: %s }] }); }); </script> <!-- Fav and touch icons --> <link rel="apple-touch-icon-precomposed" sizes="144x144" href="http://www.bootcss.com/assets/ico/apple-touch-icon-144-precomposed.png"> <link rel="apple-touch-icon-precomposed" sizes="114x114" href="http://www.bootcss.com/assets/ico/apple-touch-icon-114-precomposed.png"> <link rel="apple-touch-icon-precomposed" sizes="72x72" href="http://www.bootcss.com/assets/ico/apple-touch-icon-72-precomposed.png"> <link rel="apple-touch-icon-precomposed" href="http://www.bootcss.com/assets/ico/apple-touch-icon-57-precomposed.png"> <link rel="shortcut icon" href="http://www.bootcss.com/assets/ico/favicon.png"> <script>window["_GOOG_TRANS_EXT_VER"] = "1";</script></head> <body> <div class="container-narrow"> <div class="masthead"> <ul class="nav nav-pills pull-right"> <li><a href="http://66.xiaorui.cc:8888">Home</a></li> <li><a href="http://66.xiaorui.cc:8888/pushcmd">命令推送</a></li> <li class="active"><a href="http://66.xiaorui.cc:8888/charts.html#">图表监控</a></li> </ul> <h3 class="muted">图表监控</h3> </div> <hr> <div class="jumbotron"> <div id="container" style="width: 800px; height: 400px; margin: 0 auto"></div> <a class="btn btn-large btn-success" href="http://10.10.10.66:8888">刷新</a> </div> <hr> <hr> <div class="footer"> <h4>by xiaorui.cc</h4> </div> </div> <!-- /container --> <!-- Le javascript ================================================== --> <!-- Placed at the end of the document so the pages load faster --> </body></html> '''%p @app.route('/post/<int:post_id>') def show_post(post_id): return 'post_id:%d' % post_id @app.route('/index/') def test_session(): if 'username' in session: return 'logged in as %s' % escape(session['username']) return redirect(url_for('login')) @app.route('/login/',methods=['GET','POST']) def login(): if request.method == 'POST': session['username'] = request.form['username'] return redirect(url_for('test_session')) else: return ''' <form action="/login/" method="post"> <input type=text name=username> <input type=submit value=login> </form> ''' if __name__ == "__main__": app.run(host="10.10.10.66",port=8888,debug=True)
还有一种展现方式,就是油表
这个数据很方面的传到页面上去的。
通过后端改变value的值就行啦~
<script type="text/javascript" src="jquery.min.js"></script> <script type="text/javascript" src="jquery.knob.js"></script> <input type="text" class="dial" data-min="-40" data-max="70"> 要是不显示的话,再加上这段语句 $(".dial").knob({ 'min':-40 ,'max':70 })
这里说下 saltstack grains 的采集~ 例子如下
我要可以取出 name和lang的值。 [xiaorui.cc]
采集全部信息
salt '*' grains.items
我们通过items查看 很多的系统信息。
原文地址:http://rfyiamcool.blog.51cto.com/1030776/1266437
实时采集的话,就要取消master对grains的缓存
更新数据缓存,结果
貌似刷新有点问题~ 应该是他的一个bug吧~
经过 saltstack 专业人士 大牛 大神 帅锅 沈灿 的一段时间折腾得知,grains信息是每次客户端启动后 就确定了的 除非你每次采集钱都 重启 minion 或者 重新同步下 grains。
原文地址:http://rfyiamcool.blog.51cto.com/1030776/1266437
页面上又增加了几个功能,其实睡觉前写完了,但是有些bug
等都调试好了后,在给大家贴下实现代码。
多选控件 【xiaorui.cc】
模块上传
编辑各种 【xiaorui.cc】
连载中~
找个时间更新下~
本文出自 “峰云,就她了。” 博客,谢绝转载!