python拉取grafana监控图形

python通过grafana提供的api接口拉取grafana监控图形并保存至word文档生成日报发送邮件

前置条件:

1.grafana平台需要安装grafana-image-renderer 插件,用于生成静态图形

页面可以检查是否已安装

未安装会进入如下页面:

从API接口拉取图片会提示:

安装方式参考:

https://grafana.com/grafana/plugins/grafana-image-renderer/

该插件对内存大小有一定要求:

如果已安装该插件,点击Direct link rendered image后会显示一个静态监控图形页面

参考: https://cloud.tencent.com/document/product/1437/65674

2.在grafana页面生成api_keys,用于接口请求认证

不同版本获取方式不同 此示例为V9.2.6版,入口如下:

点击Add API key添加,可以指定有效期,弹出密钥的界面记得把密钥复制下来,否则关闭后就看不到了。

代码示例:

  • 该示例是将Grafana获取的多张图形保存到本地的panels目录下(多线程执行),
  • 通过python的Image模块进行图片拼接(拼接方式可自定义),
  • 读取日志模版文档(模版中预留了等字符用于定位),
  • 将拼好的图片插入到日志模版文档并替换文档中的日期信息,
  • 保存生成新的文档,删除本地panels目录下的图片缓存,并发送邮件。
# -*- coding: UTF-8 -*-
import smtplib
import requests
import os
import shutil
import time
from PIL import Image
from docx import Document
from docx.shared import Inches
from datetime import datetime, timedelta
from concurrent.futures import ThreadPoolExecutor, as_completed
from email.header import Header
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import make_header # 配置 Grafana API 参数
GRAFANA_HOST = "http://xxxxxxxxxxx"
# Grafana API 密钥具有时效性,如过期,请联系运维人员生成新的api_keys
API_TOKEN = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# 仪表板ID
DASHBOARD_UID = "xxxxxxxxxx"
# 图形ID
PANEL_ID_DATA = {"PANEL_1":[30,31,2,10,12,14,16,18,20,22,24,26,28],
"PANEL_2":[37, 39, 41, 43, 45, 47, 49, 51, 53],}
ORG_ID = "1"
#日志模版文件
document_path = "xxxxxxxx日志 - 模板.docx"
# 邮箱接收人
RECEIVERS = ["xxxxxx.com", "xxx.com"]
# 保存图片的文件名
folder = "panels" #邮件发送
def send_mail(filename):
sender = 'xxxxxxx.com'
receiver = ','.join(RECEIVERS)
smtpserver = 'xxxxxx.com'
user = 'xxxxxx.com'
password = 'xxxxxxxx'
mail_title = filename.split('/')[1]
mail_title = mail_title.split('.')[0]
# 创建一个带附件的实例
message = MIMEMultipart()
message['From'] = sender
message['To'] = receiver
message['Subject'] = Header(mail_title, 'utf-8') # 邮件正文内容
message.attach(MIMEText(f'hello,附件为 {mail_title},请查收,如有问题请与我联系。', 'plain', 'utf-8'))
# 构造附件
file_msg = MIMEText(open(filename, 'rb').read(), 'base64', 'UTF-8')
file_msg["Content-Type"] = 'application/octet-stream;name="%s"' % make_header([(filename, 'UTF-8')]).encode('UTF-8')
file_msg["Content-Disposition"] = 'attachment;filename= "%s"' % make_header([(filename, 'UTF-8')]).encode('UTF-8')
message.attach(file_msg)
try: smtpObj = smtplib.SMTP(smtpserver)
smtpObj.starttls()
smtpObj.login(user, password)
smtpObj.sendmail(sender, receiver, message.as_string())
print("邮件发送成功!!!")
except Exception as e:
print(e)
print("邮件发送失败!!!")
finally:
smtpObj.quit() def center_insert_img(doc, img,date_str):
"""插入图片"""
date_obj = datetime.strptime(date_str, '%Y-%m-%d')
# 将datetime对象格式化为指定的中文格式字符串
formatted_date = date_obj.strftime('%Y年%m月%d日')
for paragraph in doc.paragraphs:
# 根据文档中的占位符定位图片插入的位置
if '<datetime>' in paragraph.text:
paragraph.text = paragraph.text.replace('<datetime>', formatted_date)
elif '<img1>' in paragraph.text:
# 把占位符去掉
paragraph.text = paragraph.text.replace('<img1>', '')
# 添加一个文字块
run = paragraph.add_run('')
# 添加一个’回车换行效果‘
run.add_break()
# 添加图片并指定大小
run.add_picture(img[0], width=Inches(6.2))
elif '<img2>' in paragraph.text:
# 把占位符去掉
paragraph.text = paragraph.text.replace('<img2>', '')
# 添加一个文字块
run = paragraph.add_run('')
# 添加一个’回车换行效果‘
run.add_break()
# 添加图片并指定大小
run.add_picture(img[1], width=Inches(6.2)) def save_img_to_doc(img,day_time):
"""把图片保存到doc文件中的指定位置"""
tpl_doc = document_path
current_year = datetime.now().year
if not os.path.exists(f"{current_year}_doc"):
os.makedirs(f"{current_year}_doc")
res_doc = f'{current_year}_doc/日志报告_{day_time}.docx'
# 打开模板文件
document = Document(tpl_doc)
# 插入图片居中
center_insert_img(document, img,day_time)
# 保存结果文件
document.save(res_doc)
return res_doc def download_image(render_url, output_path, headers):
"""下载单张图片的函数"""
try:
response = requests.get(render_url, headers=headers, stream=True)
if response.status_code == 200 and "image/png" in response.headers.get("Content-Type", ""):
with open(output_path, "wb") as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
return output_path
else:
print(f"获取图形失败: {render_url}")
print(f"状态码: {response.status_code}, 返回内容: {response.text}")
return None
except Exception as e:
print(f"下载图片出错: {e}")
return None def merge_images(image_paths, output_path, layout):
"""合并图片""" images = [Image.open(path) for path in image_paths]
width, height = images[0].size
new_image = object
if layout == "grid_3xN":
num_rows = (len(images) + 2) // 3
new_image = Image.new('RGB', (3 * width, num_rows * height))
for idx, img in enumerate(images):
x, y = (idx % 3) * width, (idx // 3) * height
new_image.paste(img, (x, y))
elif layout == "grid_3x3":
new_image = Image.new('RGB', (3 * width, 3 * height))
for idx, img in enumerate(images[:9]):
x, y = (idx % 3) * width, (idx // 3) * height
new_image.paste(img, (x, y)) new_image.save(output_path)
new_image.close() def download_grafana_panel():
# start = time.time()
time_tuple = generate_daily_timestamps_and_dates()
image_paths = []
save_img_to_doc_paths = []
headers = {"Authorization": f"Bearer {API_TOKEN}"}
tasks = [] # 创建下载目录
daily_folder = f"{folder}/{time_tuple[0]}"
os.makedirs(daily_folder, exist_ok=True) # 使用线程池并行下载图片
# 此处的的URL仅供参考,I6xasdas要替换为你页面的实际值
# 也就是你点击Direct link rendered image后显示的静态监控图形页面的URL
with ThreadPoolExecutor(max_workers=5) as executor:
for PANEL_NAME, PANEL_ID_list in PANEL_ID_DATA.items():
for PANEL_ID in PANEL_ID_list:
render_url = f'{GRAFANA_HOST}/render/d-solo/I6xasdas/{DASHBOARD_UID}?orgId=1&from={time_tuple[1]}&to={time_tuple[2]}&panelId={PANEL_ID}&width=1000&height=500&tz=Asia%2FShanghai'
output_path = f"{daily_folder}/{DASHBOARD_UID}_panel_{PANEL_ID}.png"
tasks.append(executor.submit(download_image, render_url, output_path, headers)) # 收集任务结果
for future in as_completed(tasks):
result = future.result()
if result:
image_paths.append(result) # 合并图片 (第一组 3xN)
if len(image_paths) > 0:
output_path1 = f"{daily_folder}/panel_01.jpg"
merge_images(image_paths[:13], output_path1, layout="grid_3xN")
save_img_to_doc_paths.append(output_path1) # 合并图片 (第二组 3x3)
if len(image_paths) > 13:
output_path2 = f"{daily_folder}/panel_02.jpg"
merge_images(image_paths[12:21], output_path2, layout="grid_3x3")
save_img_to_doc_paths.append(output_path2) # 插入文档保存
doc_file_path = save_img_to_doc(save_img_to_doc_paths, time_tuple[0])
# 删除缓存图片
remove_dir(f"{folder}/{time_tuple[0]}")
#发送邮件
send_mail(doc_file_path)
# end_time = time.time() - start
# print(f"巡检报告成功保存并删除图片缓存!耗时{round(end_time,2)}秒") def generate_daily_timestamps_and_dates():
current_date_time = datetime.now()
# 提取日期部分并格式化为年-月-日的字符串形式
formatted_date = current_date_time.strftime('%Y-%m-%d')
# 将输入的日期字符串转换为datetime对象
start_date = datetime.strptime(formatted_date, '%Y-%m-%d')
last_day_start_date = start_date - timedelta(days=1) # 获取当天的起始时间(将时间设置为00:00:00)
start_of_day = last_day_start_date.replace(hour=0, minute=0, second=0, microsecond=0)
# 将datetime对象转换为时间戳(单位:秒)
timestamp = int(start_of_day.timestamp()*1000)
date_str = start_of_day.strftime('%Y-%m-%d') return (date_str, timestamp, timestamp + 86399*1000) def remove_dir(directory):
try:
shutil.rmtree(directory)
except OSError as e:
print(f"删除目录时出错: {e}")
if e.errno == 32: # 文件正在被占用
print("文件被占用,等待释放后重试...")
time.sleep(0.1) # 等待 0.1 秒后再次尝试
try:
shutil.rmtree(directory)
print(f"第二次尝试删除成功: {directory}")
except Exception as e2:
print(f"仍然无法删除目录: {e2}") if __name__ == "__main__":
download_grafana_panel()

python拉取grafana监控图形的更多相关文章

  1. 一步步教你用Prometheus搭建实时监控系统系列(二)——详细分析拉取和推送两种不同模式

    前言 本系列着重介绍Prometheus以及如何用它和其周边的生态来搭建一套属于自己的实时监控告警平台. 本系列受众对象为初次接触Prometheus的用户,大神勿喷,偏重于操作和实战,但是重要的概念 ...

  2. python自动拉取备份压缩包并删除3天前的旧备份

    业务场景,异地机房自动拉取已备份好的tar.gz数据库压缩包,并且只保留3天内的压缩包文件,用python实现 #!/usr/bin/env python import requests,time,o ...

  3. Python 一键拉取Git分支源码自动解析并执行SQL语句

    基于Python实现自动拉取Git分支源码自动解析并执行SQL语句 by:授客 QQ:1033553122 1.代码用途 开发过程中,研发人员会提交SQL更新脚本到Git源码库,然后测试负责去拉取这些 ...

  4. 分布式监控系统Zabbix--使用Grafana进行图形展示

      今天介绍一款高颜值监控绘图工具Grafana,在使用Zabbix监控环境中,通常我们会结合Grafana进行图形展示.Grafana默认没有zabbix作为数据源,需要手动给zabbix安装一个插 ...

  5. Centos 7安装Grafana 4及结合Zabbix3.2实现可视化监控图形

    上一篇介绍了如何在Centos 7环境下安装zabbix监控,本章继续介绍在Centos 7环境下安装Grafana,并结合Zabbix实现可视化监控图形! 简介: Grafana 是 Graphit ...

  6. Python使用又拍云进行第三方文件拉取

    在爬虫过程中,需要将图片或其他文件进行存储到云上,但在下载图片时,看官方文档,貌似需要先下载到后再上传又拍云,感觉效率很低下.经查找资料实现Python直接对第三方资源进行文件拉取操作,即不需要下载到 ...

  7. python 写了一个批量拉取文件进excel文档

    路径如: C:\\Users\\huaqi\\Desktop\\信息收集 “信息收集”目录下有以下子目录:[技术,客服,运营,行政] “技术”目录下有以下子文件:[小白.txt,小红.txt,小黑.t ...

  8. Ubuntu上Grafana 监控 Docker的技巧

    导读 Grafana 是一个有着丰富指标的开源控制面板.在可视化大规模测量数据的时候是非常有用的.根据不同的指标数据,它提供了一个强大.优雅的来创建.分享和浏览数据的方式. 它提供了丰富多样.灵活的图 ...

  9. kubernetes(k8s) Prometheus+grafana监控告警安装部署

    主机数据收集 主机数据的采集是集群监控的基础:外部模块收集各个主机采集到的数据分析就能对整个集群完成监控和告警等功能.一般主机数据采集和对外提供数据使用cAdvisor 和node-exporter等 ...

  10. Prometheus Grafana监控全方位实践

    这次就不用 docker 部署服务了,这样大家会更容易接受.欢迎阅读. 引言 Prometheus 是一个监控系统,也是一个时间序列数据库,用Go语言开发的,官方文档.通过从某些特定的目标如主机,My ...

随机推荐

  1. ArgoWorkflow教程(四)---Workflow & 日志归档

    上一篇我们分析了argo-workflow 中的 artifact,包括 artifact-repository 配置以及 Workflow 中如何使用 artifact.本篇主要分析流水线 GC 以 ...

  2. Stooges – AI 孙燕姿

    很久没有写文章了... 最近听了 AI 孙燕姿 的一首歌 <一场游戏一场梦>, 有感而发. 所以特别写一篇记入一下我的这半年很火的 AI 的想法.

  3. 【QT性能优化】QT性能优化之QT6框架高性能网络编程框架实现百万TCP长连接网络服务器:QT是否适合做高性能网络应用?补天云这个视频告诉你在大厂Linux云服务器上的实测结果

    QT性能优化之QT6框架高性能网络编程框架实现百万TCP长连接网络服务器 Ø 简介 本文作者编写了一套基于QT的TCP网络服务器程序和基于QT的TCP客户端程序,在某大厂的云服务器上进行了C1000K ...

  4. Flutter(able) 的单例模式

    文/ 杨加康,CFUG 社区成员,<Flutter 开发之旅从南到北>作者,小米工程师 单例设计模式(Singleton Design Pattern)理解起来非常简单. 一个类只允许创建 ...

  5. Kubernetes Pod原理(十六)

    一.Pod Kubernetes 最基本的调度单元 前面我们了解了 Kubernetes 的基本架构,以及如何使用资源清单在集群中部署一个应用.我们也了解到了 Pod 是 Kubernetes 集群中 ...

  6. YashanDB个人版正式开放下载!参与首批体验官活动赢好礼!

    好消息!国产数据库YashanDB个人版已正式向所有用户和开发者全面开放下载,该版本已在官网同步上线,欢迎大家前往官网下载体验! 与此同时,YashanDB联合墨天轮技术社区启动首批「产品体验官」尝鲜 ...

  7. 011 Python 的打印(花式变色打印)和注释(为什么加个#号就能注释)

    #!/usr/bin/env python # -*- coding:utf-8 -*- # Datatime:2022/7/18 21:29 # Filename:011 Python 的打印和注释 ...

  8. 工作使用:Exchange命令集(超级重要)

    工作使用:Exchange命令集(超级重要) 命令1:导出某个用户的邮件                  New-MailboxExportRequest   -mailbox  dusonglin ...

  9. 记一次CPU飙升的问题排查

    1.背景 通过公司监控工具监控,发现公司某个应用cpu利用率达到120%,也就是说这个应用自己单独占用一个cpu使用,为何占用这么高?让我们一起排查一下 2.开始排查 (1) 第一步获取cpu过高应用 ...

  10. LaMI-DETR:基于GPT丰富优化的开放词汇目标检测 | ECCV'24

    现有的方法通过利用视觉-语言模型(VLMs)(如CLIP)强大的开放词汇识别能力来增强开放词汇目标检测,然而出现了两个主要挑战:(1)概念表示不足,CLIP文本空间中的类别名称缺乏文本和视觉知识.(2 ...