这篇文章是在上篇增加了bosun grafana plugin之后,在设置bosun的grafana dashboard时,发现了dashboard template
的一个问题的临时处理办法的总结。
背景
比如我们在设置dashboard时,一般一个dashboard是有多个图的: 在设置图的query的时候,每个图都要修改host参数,如: 也就是说,如果有10张图,那我们得修改十次这个值,所以当一个dashboard较多图的时候,设置template是很有必要的,我们可以将查询语句统一写为:
q("sum:rate{counter,,1}:os.cpu(host=$host)","$start","")
然后设置template:
具体可以参考官方文档
问题
但是bosun的grafana plugin貌似有个bug,直接报错了:
我又不懂javascript,怎么办?试了下,使用custom
是可以的,不过需要自己手动填,如"192.168.1.1,192.168.1.2":
当然是非常不靠谱的方法,如机器多,填起来也麻烦,每当一个被监控机器加入的时候,又得手动填,更麻烦了。
在找了很多资料无果的情况下,只好自己尝试解决了。
首先是想找到有没有什么配置文件里面定义了这个值,只要我们获取下bosun api返回的tagv,然后用sed之类的更新下配置文件,是不是就可以解决了呢?
不过很遗憾,配置是写在一个sqlite3数据库里的,如下:
一整串json
!借助了这个格式化输出json的网站,看了下结构,主要涉及的是以下key:
"current": {
"text": "192.168.1.1",
"value": "192.168.1.1"
}
"options": [
{
"selected": true,
"text": "192.168.1.1",
"value": "192.168.1.1"
}
{
"selected": false,
"text": "192.168.1.2",
"value": "192.168.1.2"
}
]
"query": "192.168.1.1,192.168.1.2"
测试了update指令,更新了数据库,发现确实可以在页面上显示出增加了主机。万事俱备,只欠写个python脚本了。
解决方法
以下是我用来更新template的python脚本,仅为能用而已,没有考虑错误处理等:
#!/usr/local/bin/python
#coding:utf8
import sqlite3
import re
import json
import requests
granfa_db = "/var/lib/grafana/grafana.db"
template_titles = {"host":"单个机器数据模板", "game":"单个游戏服数据模板"}
bosun_api = {"host":"http://localhost:8070/api/tagv/host/scollector.hi", "game":"http://localhost:8070/api/tagv/node/application.game.hi"}
regexs = {'options':r'"options":\[[^]]+\]', 'query':r'"query":"[^"]+"'}
def get_template_data(query):
if query == "host" or query == "game":
conn = sqlite3.connect(granfa_db)
cursor = conn.execute('''select data from dashboard where title = "%s"''' % template_titles[query])
return cursor.fetchall()[0][0]
else:
return []
def update_template(query, data):
if query == "host" or query == "game":
conn = sqlite3.connect(granfa_db)
cursor = conn.execute('''update dashboard set data = '%s' where title = "%s"''' % (data, template_titles[query]))
conn.commit()
def query_bosun(query):
if query == "host" or query == "game":
return [item for item in json.loads(requests.get(bosun_api[query]).text)]
else:
return []
def assemble_options(query):
if query == "host" or query == "game":
options = '''{"selected":false,"text":"A","value":"A"}'''
query_ret = query_bosun(query)
options_ret = []
for item in query_ret:
options_ret.append(re.sub('A', item, options))
return '''"options":[%s]''' % re.sub("false", "true", ",".join(options_ret), 1)
else:
return []
def assemble_query(query):
if query == "host" or query == "game":
queries = '''"query":"A"'''
query_ret = ",".join(query_bosun(query))
return '''"query":"%s"''' % query_ret
else:
return ""
def assemble_data(query):
if query == "host" or query == "game":
new_data = re.sub(regexs['options'], assemble_options(query), get_template_data(query))
new_data = re.sub(regexs['query'], assemble_query(query), new_data)
return new_data
if __name__ == "__main__":
new_data = assemble_data("host")
update_template("host", new_data)
new_data = assemble_data("game")
update_template("game", new_data)
然后设置定时任务,每半小时更新一次,足够了。
效果如下:
缺陷
当然是不能实时更新了,还要自己写脚本这么蛋疼。
后记
目前(2016/12/05)最新版本的bosun插件已经没有上述问题了。