Open-falcon運維監控系統——微信接口二次開發
OpenFalcon是一款由小米運維團隊從互聯網公司的需求出發, 根據多年的運維經驗,結合市面上使用的一些運維監控系統的使用經驗和反饋,開發的一套企業級、高可用、可擴展的開源監控解決方案。簡單了使用一下Open-falcon運維監控,結合使用過的zabbix,cacti,nagios來說,覺得有以下幾個優點:
- 支持用戶主動push,可以結合一些業務需求采集數據,同時也支持用戶自定義的插件。
- 支持策略模板,模板繼承和覆蓋,多種告警方式,支持callback調用
- 由於dashboard采用的是rrd數據,結合rrdtool的數據歸檔策略,可以及時返回歷史數據
- 多維度的數據展示,用戶可以自定義Screen。
- 有著完善的開源社區,開源社區提供了各種第三方應用的監控插件。目前的插件支持Linux、Windows、Mysql、Redis、Memache、RabbitMQ和交換機監控。
在這裏就不再贅述Open-falcon運維監控系統各種組件,以及如何部署,官方文檔寫的十分明白,有興趣的可以去看看官方文檔。
官方文檔地址:http://book.open-falcon.org/
Open-falcon的github地址:https://github.com/open-falcon/
2、遇到的問題
在使用Open-falcon的過程中遇到過這麽一個問題,就是在發送微信報警的時候,發現只能綁定一個企業微信中的應用,如果監控的機器多起來,各種類型的報警成堆的在一個微信應用中出現。所以面對不同的報警類型的告警信息需要把他歸類在不同的應用發送,這樣面對不同的問題時便可以更加方便的解決。查看了官方提供的微信網關,研究了一下,官方使用go語言寫,對於go語言沒怎麽接觸,所以打算用python寫一個微信的接口,能夠自定義添加綁定不同的應用。
官方的微信接口:https://github.com/Yanjunhui/chat
3、解決的方案及思路
大概思路就是,python從wechat.conf配置文件中提取配置信息,定時獲取微信的access_token,並且存入到指定access_token.conf的配置文件中,綁定端口監聽Open-falcon發送過來的數據,解析提取關鍵的信息,判斷告警類型,並且從access_token.conf配置文件中獲取指定應用access_token,然後發送到指定的url。
企業微信API:https://work.weixin.qq.com/api/doc
4、詳細解決方法及代碼分析
4.1、首先需要統一配置文件的格式:wechat.conf、access_token.conf
wechat.conf
access_token.conf
4.2、獲取wechat.conf配置文件的配置項,定時獲取access_token
def get_accesstoken():
url = ‘https://qyapi.weixin.qq.com/‘
ap = ConfigParser.SafeConfigParser()
cp = ConfigParser.SafeConfigParser()
ap.read(‘./config/wechat.conf‘)
config = ap.sections()
for i in config:
if i != ‘http‘ and i != ‘weixin‘:
agentid = ap.get(i, ‘AgentId‘)
corpid = ap.get(i, ‘CorpID‘)
corpsecret = ap.get(i, ‘Secret‘)
token_url = ‘%s/cgi-bin/gettoken?corpid=%s&corpsecret=%s‘ % (url, corpid, corpsecret)
access_token = json.loads(urllib.urlopen(token_url).read().decode())[‘access_token‘]
cp.add_section(i)
cp.set(i,"AgentId",agentid)
cp.set(i, "access_token", access_token)
cp.write(open(‘./config/access_token.conf‘,‘w‘))
global timer
timer = threading.Timer(3600,get_accesstoken)
timer.start()
4.3、收集Open-falcon發送到端口的數據
關鍵代碼如下:
#繼承threading.Thread類,重寫方法,綁定指定端口,接收數據
def __init__(self,port):
threading.Thread.__init__(self)
self.port = port
self.sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
self.sock.bind((‘0.0.0.0‘,port))
self.sock.listen(0)
#對於接收到的數據進行url解碼
def run(self):
while True:
data = self.client.recv(BUFSIZE)
if(data):
string = urllib.unquote(data)
self.handle_String(string)
#print string
else:
break
4.4、對於獲取到的數據進行字符串截取
具體用法如下圖:
字符串截取代碼具體如下:
def handle_String(self,s):
a = s.split(‘&‘)
dict = {}
for i in range(len(a)):
if len(re.split(‘\[‘,a[i]))>1:
dict[‘content‘]=re.split(‘content=‘,a[i])[1]
elif len(re.split(‘tos=‘,a[i]))>1:
dict[‘tos‘]=re.split(‘tos=‘,a[i])[1]
flag = re.split(‘\[‘,dict[‘content‘])[5].split(‘*‘)[0]
touser = dict[‘tos‘]
content = dict[‘content‘]
obj = wechat.Weixin(flag, content)
obj.message(touser)
logging.debug(‘Send to %s Wechat %s %s ‘ % (touser,flag,content))
4.5、對於截取過的數據封裝在對象中,並且判斷獲取指定的access_token和配置項,封裝發送。
關鍵代碼如下:
def message(self,touser):
url = ‘https://qyapi.weixin.qq.com/‘
cp = ConfigParser.SafeConfigParser()
ap = ConfigParser.SafeConfigParser()
cp.read(‘./config/wechat.conf‘)
ap.read(‘./config/access_token.conf‘)
config = cp.sections()
access_config = ap.sections()
agentname = ‘test4‘
agentid = cp.get(‘test4‘, ‘AgentId‘)
self.token = ap.get(‘test4‘,‘AgentId‘)
#遍歷配置項是否有對應告警類型的應用
for i in config:
if i !=‘http‘ and i!= ‘weixin‘:
value = cp.get(‘weixin‘,i)
if self.flag == value:
agentname = i
agentid = cp.get(i, ‘AgentId‘)
for k in access_config:
if k == agentname:
self.token = ap.get(k,‘access_token‘)
values = {
"touser": touser,
"msgtype": ‘text‘,
"agentid": agentid,
"text": {‘content‘:self.content},
"safe": 0
}
return self.send_message(url,json.dumps(values))
4.6、發送告警信息到指定應用
關鍵代碼如下:
def send_message(self,url,data):
send_url = "%s/cgi-bin/message/send?access_token=%s" %(url,self.token)
self.response = urllib.urlopen(urllib.Request(url=send_url,data=data)).read()
x = json.loads(self.response.decode())[‘errcode‘]
if x==0 :
logging.debug(‘Successfully %s ‘ % (data))
return ‘Successfully‘
else:
logging.debug(‘Faild %s‘ % (data))
return ‘Failed‘
**最後效果圖**
總結
因為只在自己的幾臺虛擬機上運行,暫時還沒發現出問題。如果有什麽問題希望大家指正,自己學python不久,自己寫這個東西學到了很多,遇到問題就不要怕解決,就怕不思考。
接口的源代碼:https://github.com/libuliduobuqiuqiu/openfalcon-wechat
Open-falcon運維監控系統——微信接口二次開發