1. 环境依赖
首先
npm install -g phantomjs-prebuilt
笔者 python 2.7.15 的环境,requirements.txt 如下:
jinja2>=2.8
future
lml>=0.0.2
jupyter-echarts-pypkg>=0.1.1
pyecharts-javascripthon
pyecharts-snapshot==0.1.10 # > 0.1.10 以上版本仅支持python 3+
pyecharts==0.5.10 # pyecharts v1 版本仅支持python 3.6+
2. 了解 docx 的结构
推荐两篇文章:
- https://www.cnblogs.com/zhanghongfeng/p/7043412.html
- https://blog.csdn.net/qwe125698420/article/details/70622289?locationNum=3&fps=1
发现 docx 与 xml 关系密切,所以我们以 xml 为模板,最后从 xml 转换为 docx 文件
3. 我的模板
使用 docx 文件创建模板,另存为 xml 文件
4. 获取 prometheus 数据
利用 prometheus 提供的 http 查询方式获取一组待分析数据。
def get_prom_data():
url = ("http://{host}:{port}/api/v1/query_range?query=ping_delay<peer='{peer}',"
"source='{source}'>&start={start_time}&end={end_time}&step=14")
end_time = time.time()
start_time = end_time - 3600 # 取 1小时数据
qyery_url = url.format(host="xx", port="xx", peer="xx", source="xx",
start_time=start_time, end_time=end_time)
status_url = qyery_url.replace("<", "{").replace(">", "}")
data = {}
rsp = do_request(status_url)
if rsp.get("status", "") == "success" and rsp.get("data", {}).get("result", []):
data = rsp["data"]["result"][0]["values"]
if not data:
raise Exception("prometheus data not found"
return data
4. 数据制图
使用 pyecharts 将从 prometheus 获取的数据制作城图形,选择合适的图形来表达自己的数据,这里我使用了饼图来表达“链路延迟等级分布”。
from pyecharts import Bar, Pie, Grid, Line, Overlap
def create_a_pic():
prom_data = get_prom_data()
attr = ["良好", "正常", "警告", "严重"]
good, nomal, warn, cri = parse_data(prom_data)
pie = Pie("链路延迟等级分布图")
pie.add("delay", attr, [good, nomal, warn, cri], is_random=True, radius=[30, 75])
pie.render(path="test.png")
5. 生成图片信息流
将图片以 bytes 读取,并使用 base64 加密。
def get_encoded_pic(path):
"""
将图片转化为字节数据
:param path: 图片的路径
:return: 加密的字节数据
"""
if not os.path.exists(path):
raise Exception("{} not exists".format(path))
with open(path, "rb") as f:
data = base64.standard_b64encode(f.read())
return data
6. 图片放入模板
将上一步生成的图片信息流放入到模板,其中的难点就是编码问题。懂得Python的都知道python2的编码问题,碰到过的几乎都吐血一升。
def writeback_xml(data):
"""
data 是编译图片生成的 bytes 格式的字符串,
data.decode("utf-8")将 bytes 解码成unicode,
render 之后是 str 格式,但是 f.write() 需要 unicode 格式,
所以使用 encode("utf-8")
:param data: 图片的字节数据
:return:
"""
env = Environment(loader=FileSystemLoader(PWD))
template = env.get_template("test.xml")
with open(NEW_XML_PATH, "wb") as f:
f.write(template.render(pic=data.decode("utf-8")).encode("utf-8"))
6. 完成报表
将上面生成的 xml 文件另存为 docx 格式即可