惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Fortinet All Blogs
WordPress大学
WordPress大学
The Cloudflare Blog
云风的 BLOG
云风的 BLOG
博客园 - Franky
D
Docker
小众软件
小众软件
阮一峰的网络日志
阮一峰的网络日志
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Engineering at Meta
Engineering at Meta
MongoDB | Blog
MongoDB | Blog
U
Unit 42
M
MIT News - Artificial intelligence
B
Blog
GbyAI
GbyAI
C
Check Point Blog
P
Proofpoint News Feed
博客园 - 司徒正美
Hugging Face - Blog
Hugging Face - Blog
雷峰网
雷峰网
IT之家
IT之家
Google DeepMind News
Google DeepMind News
V
V2EX
Stack Overflow Blog
Stack Overflow Blog

杂烩饭

为什么 Prometheus 监控不到 Pod 磁盘空间?原因分析与解决 使用RetroArch玩步步高电子词典游戏 彻底删除CCLibrary 在 Nginx 中禁止 IP 直连与域名暴露 使用 RustFS 自建对象存储 使用cURL命令管理对象存储(s3) AGENTS.md Prometheus使用kubeconfig做k8s的service 自动发现监控 定制Windows系统镜像iso 使用create-dmg工具制作dmg安装包 使用create-dmg工具制作dmg安装包 - 技术栈 superpowers Nexus仓库搭建记录 Git Merge代码冲突的解决方式 在 Linux 系统中安装与配置 OpenVPN:从入门到精通 使用 Easytier-web 管理 easytier 节点 ingress-nginx 去除指定context path 在macOS上使用MusicPlayer2听本地音乐 Kubernetes 1.34 + RHEL10 + Cilium + kube-vip 高可用集群部署 使用腾讯云CLS收集TKE(k8s)业务日志 容器调试工具之BusyBox 无Docker环境进行容器镜像操作 使用kubeadm部署一套高可用k8s集群1.34 for Ubuntu 正在运行的Docker容器增加端口映射 轻量级组网工具WireGuard 在Kubernetes中部署一个单节点Elasticsearch 使用openssl制作自签名双向认证(mTLS)证书 minio自建对象存储 ingress-nginx 使用自定义的nginx配置 P12格式证书与PEM格式转换
使用selenium来实现Grafana的自动截图
张理坤 · 2025-04-18 · via 杂烩饭

selenium 是一个 python 库, 用于操作 chromium 浏览器实现一些自动化的动作, 本文是为了把 grafana 的监控图截图保存, 后续可以将图片做成运维报表之类的.

调试阶段

调试阶段可以使用电脑上的 chrome,并关闭 headless 模式,方便看到界面执行的效果.
chrome 官网下载即可, chromedriver 下载地址: https://googlechromelabs.github.io/chrome-for-testing/ , chromedriver 放在代码同目录即可.

问题

为什么不用 grafana-image-renderer, 这个官方插件 BUG 挺多的, 比如一个图需要很长时间才能加载, 就会出现图还没加载出来, 就完成了截图的情况. 并且截图速度很慢.

简单的开始

1
pip install selenium
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service

chrome_options = Options()
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument("--disable-extensions")



ser = Service()



driver = webdriver.Chrome(options=chrome_options, service=ser)


driver.set_window_size(1920, 1080)


driver.get("https://grafana.example.com/login")


driver.close()

正常的话, 可以打开页面了, 然后浏览器会自动关闭.

查找元素

从浏览器开发工具查找元素

比如说在 grafana 登陆界面,我想自动输入账号密码进行登录,那么可以使用

image.png

在这里可以找到名字, 可以根据 NAME 来定位,也可以根据 class 定位.

1
2
3
4
5
6
7

username_input = driver.find_element(By.NAME, "user")
password_input = driver.find_element(By.NAME, "password")
login_button = driver.find_element(By.XPATH, '//button[@type="submit"]')
username_input.send_keys(self.username)
password_input.send_keys(self.password)
login_button.click()

等待元素出现

比如我打开某个 panel 仪表板的全屏界面后, 我想等这个界面加载出来再继续,可以通过:

1
2
3
4
5
6

WebDriverWait(driver, 30).until(
EC.presence_of_element_located(
(By.XPATH, '//*[@class="css-itdw1b-panel-container"]')
)
)

这里的 XPATH 获取方式:
image.png

等待元素消失

比如说查看一个长时间的监控图像, 会加载很久, 这个时候需要等待图加载出来后再进行截图,我们可以监视页面上的加载 icon,等这个 icon 消失表示加载完成.
image.png

代码如下:

1
2
3
4
5
6

WebDriverWait(driver, 60).until(
EC.invisibility_of_element_located(
(By.XPATH, '//*[@class="css-1p4srcl-Icon"]')
)
)

针对指定的 panel 进行截图

1
2
3
4
5
6

panel = driver.find_element(By.XPATH, '//*[@class="css-itdw1b-panel-container"]')


safe_filename = re.sub(r'[\\/*?:"<>|]', '_', self.panel_title) + '.png'
panel.screenshot(safe_filename)

当然也可以直接全屏截图.

中文乱码问题

截图如下:
image.png

修复方式为: 安装中文字体:

1
2

apt-get install -y ttf-wqy-microhei

image.png

完整代码

https://github.com/iuxt/grafana_auto_capture_image

容器化

我们最终是要以容器的形式在 Kubernetes 上的 cronjob 来定时执行. 考虑到安装 chromium 依赖非常多, 直接使用发行版源里的 chromium 更方便, 首先排除新版 ubuntu, ubutnu 的 chromium 被 snap 包替代了, 所以选择了 debian:12 镜像.

dockerfile 如下:

1
2
3
4
5
6
7
8
FROM debian:12
RUN sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list.d/debian.sources && \
apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y -qq \
chromium chromium-driver python3-pip python3-venv \
ttf-wqy-microhei
ADD code /code
CMD ["python3", "main.py"]