使用node_exporter采集自定义指标
背景
node_exporter 用于采集Linux system的监控指标提供给prometheus抓取。当需要收集某些具体进程状态,或者系统内其他期望自定义的参数时,node_exporter原生collector并不能够支持。
有两种方式可以实现采集操作系统下需要的自定义指标
- 二次开发新增collector
- textfile模块采集指定的文件下保存的指标。
此次的需求为采集CentOS 7,/var/log/message中的oom log。
二次开发添加collector
待实验
textfile模块
启动参数配置
增加 --collector.textfile.directory 参数
使用systemd管理node_exporter
[Unit]
Description=Prometheus Node Exporter
After=network.target
[Service]
Type=simple
User=root
Group=root
Nice=-5
ExecStart=/usr/local/bin/node_exporter \
--collector.systemd \
--collector.textfile.directory=/var/lib/node_exporter \
--web.listen-address=0.0.0.0:9100
SyslogIdentifier=node_exporter
Restart=always
[Install]
WantedBy=multi-user.target
编写脚本产生指标文件
脚本产生的指标文件,存放在 --collector.textfile.directory 参数指定的路径下,文件名以.prom结尾
采集 CentOS oom log
prometheus text-based格式
-
每行必须使用换行符\n结束,空行会被忽略。
-
#符号开头,后面不接HELP或TYPE的行,视为注释。
-
# HELP开头,后面第一个字段是metric名,再后面的字段或字符被视为对metric的描述。
-
# TYPE开头,后面第一个字段是metric名,第二个字段是metric类型,metric类型有counter, gauge, histogram, summary, or untyped。
-
同的metric名只能有一个TYPE,并且TYPE这行要放在metric取样之前,如果没有为metric设置TYPE,metric类型被设置为untyped。
期望的指标文件内容和格式
cat /var/lib/node_exporter/oomkill.prom
# HELP messages_log_oomkill /var/log/messages oomkill.
# TYPE messages_log_oomkill counter
messages_log_oomkill{topic="Feb 12 15:50:23 test-node kernel: cloudprovider invoked oom-killer: gfp_mask=0x120cca(GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=996"} 1
使用计划任务执行采集脚本
采集脚本
- 过滤从当前往前推5分钟内的oomkill日志。
- 有多条的话,逐条打印监控指标。
- 没有满足的日志时,只执行对指标文件置空,避免反复上传历史数据。
- 不同的oom日志,以topic="***",将具体日志以lables形式传入metric。
- 替换log中可能存在的",避免不满足prometheus textfile格式。
cat get_oomlog.sh
# 收集n分钟内 /var/log/messages 下的oomkill log,注册为node_exporter指标
# 设定读取的日志文件路径
log_file='/var/log/messages'
# 设定读取哪几分钟内的日志
minutes_count=50
metric_name='messages_log_oomkill_5m'
node_exporter_config_dir='/var/lib/node_exporter'
tmp_dir="/tmp"
# 清空历史
cat /dev/null > $tmp_dir/var_log_message_oomkill
cat /dev/null > $node_exporter_config_dir/oomkill.prom.
cat /dev/null > $node_exporter_config_dir/oomkill.prom
# 过滤5分钟内的oomkill日志
for i in `seq 0 $[$minutes_count-1]`
do
ntime=`date -d "$i minute ago $date" +%b" "%d" "%H:%M`
echo $ntime
cat $log_file|grep "$ntime"|grep oom-killer >> $tmp_dir/var_log_message_oomkill
done
# 替换log中可能存在的",避免不满足prometheus textfile格式
sed -i 's/"/|/g' $tmp_dir/var_log_message_oomkill
# 逐行读取过滤后的日志,追加至指标文件模板
if [ -s $tmp_dir/var_log_message_oomkill ];then
cat > $node_exporter_config_dir/oomkill.prom. <<EOF
# HELP $metric_name /var/log/messages oomkill.
# TYPE $metric_name gauge
EOF
while read row
do
echo $metric_name{topic=\"$row\"} 1 >> $node_exporter_config_dir/oomkill.prom.
done < $tmp_dir/var_log_message_oomkill
fi
# cat $node_exporter_config_dir/oomkill.prom.
# 生成指标文件
mv $node_exporter_config_dir/oomkill.prom. $node_exporter_config_dir/oomkill.prom
crontab配置每分钟执行一次
# crontab -l -e
* * * * * /bin/sh get_oomlog.sh
测试指标是否成功上传
node_exporter采集时间由prometheus配置的scrape_interval决定,在等待一个采集周期过后进行测试
查看服务状态,若文件格式有问题,将直接体现在systemd log中。而正常情况下,正确的采集不打印info日志(由启动参数决定)
错误示例:
# systemctl status node_exporter.service -l
● node_exporter.service - Prometheus Node Exporter
Loaded: loaded (/etc/systemd/system/node_exporter.service; enabled; vendor preset: disabled)
Active: active (running) since Sun 2023-02-12 19:17:27 CST; 31s ago
Main PID: 27372 (node_exporter)
Tasks: 5
Memory: 15.0M
CGroup: /system.slice/node_exporter.service
└─27372 /usr/local/bin/node_exporter --collector.systemd --collector.textfile.directory=/var/lib/node_exporter --web.listen-address=0.0.0.0:9100
Feb 12 19:17:27 centos-ops node_exporter[27372]: ts=2023-02-12T11:17:27.132Z caller=node_exporter.go:115 level=info collector=time
Feb 12 19:17:27 centos-ops node_exporter[27372]: ts=2023-02-12T11:17:27.132Z caller=node_exporter.go:115 level=info collector=timex
Feb 12 19:17:27 centos-ops node_exporter[27372]: ts=2023-02-12T11:17:27.132Z caller=node_exporter.go:115 level=info collector=udp_queues
Feb 12 19:17:27 centos-ops node_exporter[27372]: ts=2023-02-12T11:17:27.132Z caller=node_exporter.go:115 level=info collector=uname
Feb 12 19:17:27 centos-ops node_exporter[27372]: ts=2023-02-12T11:17:27.132Z caller=node_exporter.go:115 level=info collector=vmstat
Feb 12 19:17:27 centos-ops node_exporter[27372]: ts=2023-02-12T11:17:27.132Z caller=node_exporter.go:115 level=info collector=xfs
Feb 12 19:17:27 centos-ops node_exporter[27372]: ts=2023-02-12T11:17:27.132Z caller=node_exporter.go:115 level=info collector=zfs
Feb 12 19:17:27 centos-ops node_exporter[27372]: ts=2023-02-12T11:17:27.132Z caller=node_exporter.go:199 level=info msg="Listening on" address=0.0.0.0:9100
Feb 12 19:17:27 centos-ops node_exporter[27372]: ts=2023-02-12T11:17:27.132Z caller=tls_config.go:195 level=info msg="TLS is disabled." http2=false
Feb 12 19:17:54 centos-ops node_exporter[27372]: ts=2023-02-12T11:17:54.796Z caller=textfile.go:227 level=error collector=textfile msg="failed to collect textfile data" file=oomkill.prom err="failed to parse textfile data from \"/var/lib/node_exporter/oomkill.prom\": text format parsing error in line 3: expected '\"' at start of label value, found 'F'"
curl方式确认是否成功采集
curl 127.0.0.1:9100/metrics|grep oomkill
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0# HELP messages_log_oomkill /var/log/messages oomkill.
# TYPE messages_log_oomkill counter
messages_log_oomkill{topic="Feb 12 15:42:23 test-node kernel: cloudprovider invoked oom-killer: gfp_mask=0x120cca(GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=996"} 1
看到指标已被node_exporter正确的采集,prometheus将会主动抓取它,可供grafana或alertmanger等监控告警平台进行消费。