排障
Categraf 的问题按现象分三类:主机不出现、主机在但没指标、某个插件没数据;答案几乎都在日志里,包括不以 E! 标记的错误。
Categraf 侧的问题基本都能在日志里看出来,前提是知道去哪看、以及哪些错误不是 E! 级别。
这页按现象分三类:主机不出现、主机在但没指标、某个插件没数据。
先看日志
默认 [log] file_name = "stdout",装成系统服务之后就是 journal:
journalctl -u categraf -n 100 --no-pager
journalctl -u categraf -f # 跟踪
想落到文件,改 conf/config.toml:
[log]
file_name = "/var/log/categraf/categraf.log"
max_size = 100 # MB
max_age = 1 # 天
max_backups = 1
日志级别写在每行开头:I! 信息、W! 警告、E! 错误、F! 致命。
这里有个坑:写入失败的日志是 W!,不是 E!。 只 grep E! 会把「数据一直发不出去」
这个最常见的问题完整漏掉。查写入问题请 grep W! 或者直接看 push data:
journalctl -u categraf | grep -E 'W!|E!|F!'
另外,配置文件本身加载失败的那条日志走的是 stderr,不受 [log] 控制——
如果你把日志重定向到文件,然后进程起不来、文件里又什么都没有,去看 stderr(journal 里有):
F! failed to init config: ...
主机不出现在设备列表里
按顺序排查:
1. 进程活着吗。
systemctl status categraf
2. 心跳开着吗。 conf/config.toml 里:
[heartbeat]
enable = true
url = "http://10.0.0.10:17000/v1/n9e/heartbeat"
包里自带的示例地址是 指向的是打包时残留的某台开发机,对你一定是无效的, 装完忘了改是最常见的原因。
3. 心跳发出去了吗。 日志里搜:
E! failed to do heartbeat: ...
E! heartbeat status code: 401 response: ...
- connection refused / timeout:网络不通,在这台机器上
curl -v <夜莺地址>试试; - 401:服务端开了 BasicAuth,
[heartbeat] basic_auth_user/pass要填上; - 404:地址写错了,路径必须是
/v1/n9e/heartbeat;也可能是服务端把[HTTP.APIForAgent] Enable关了。
4. 什么日志都没有? 试试前台跑一次,只跑心跳:
/opt/categraf/categraf --configs /opt/categraf/conf --debug --inputs heartbeat
5. 出现了但又消失了。 检查有没有 hostname 撞车——两台机器用同一个 hostname 时, 夜莺里只有一条记录,两边的元信息交替覆盖,不会有任何告警。 看「来源 IP」和「AGENT版本」这两列是不是在两个值之间来回跳。
主机在,但没有指标
心跳和写入是两条独立的链路,心跳通不代表指标通。
1. 写入地址对不对。
[[writers]]
url = "http://10.0.0.10:17000/prometheus/v1/write"
路径是 /prometheus/v1/write,不是 /prometheus/api/v1/write(后者是时序库的接口,
不是夜莺 pushgw 的)。
2. 日志里有没有写入失败。 一次失败会打三行,都是 W!:
W! push data with remote write request got error: Post "http://...": dial tcp ...: connection refused response body:
W! post to http://... got error: ...
W! example timeseries: labels:<name:"__name__" value:"mem_total" > ...
第三行会举一条这批里的样本,能看出丢的是哪部分数据。返回非 2xx 时是:
W! post to <url> got error: push data with remote write request got status code: 401, response body:
记住写入失败没有重试,这一批数据就丢了。所以看到这些行,除了修问题, 还要知道这段时间的数据是补不回来的。
3. 队列满了。
E! write 1000 samples failed, please increase queue size(1000000)
这条说明产出比发送快。先查后端是不是慢或不通,确认后端没问题再调大
[writer_opt] chan_size——后端不通的时候调大队列只是让丢数据晚一点发生。
4. 查错了数据源。 指标写进了 A,你在 B 里查。默认落在内置时序库
(数据源名 embedded-tsdb),配了 Pushgw.Writers 转发的话要去对应的数据源里查。
某个插件没数据
1. 插件启用了吗。 启动日志里找:
I! input: local.mysql started
E! input: local.jolokia_agent_kafka not supported
not supported 说明 conf/input.<名字>/ 这个目录名对不上任何插件。
包里自带的 input.jolokia_agent_kafka/、input.jolokia_agent_misc/、
input.amd_rocm_smi/ 就是这种情况,删掉即可。
2. 一行日志都没有? 这是多实例插件最典型的表现:必填字段没填时,插件会被静默跳过,
不报错也不打 started。加 --debug 才看得见:
W! no instances for input:mysql
包里自带的示例配置默认全是注释掉的,所以「有 input.mysql 目录但没数据」,
八成就是 [[instances]] 里一个字段都没填。
3. 单独试采一次。
/opt/categraf/categraf --configs /opt/categraf/conf --test --inputs mysql
--configs 一定要用绝对路径:Categraf 启动时会把工作目录切到自己二进制所在的目录,
相对路径会解析到 categraf 安装目录下,不是你当前 shell 的目录。
看到指标行说明插件本身没问题,问题在写入侧。看不到就是连不上目标或者权限不够, 错误信息一般会直接说。
顺带一句:--test 不会关掉心跳,它照样往夜莺发心跳,
所以在生产机器上随手跑一次也会刷新设备列表里的记录。
4. 插件 panic。
E! mysql : gather metrics panic: ... <堆栈>
panic 会被兜住,reader 不会死,下个周期继续采。带上堆栈去 categraf issues 提一个。
数据到了,但标签不对
- 少了
agent_hostname:[global] omit_hostname被设成了 true, 或者插件的labels里显式占了这个键; - 想删掉某个标签:在
labels里把它的值写成"-",比如labels = { region = "-" }; - 在夜莺里打的机器标签没出现在指标上:这些标签是夜莺在转发时附加的,
所以 Categraf 必须写给夜莺(而不是直连时序库),并且服务端
Pushgw.LabelRewrite要是打开的; - 上报的标签和自定义标签键名撞了:上报的赢,自定义的那条被丢掉。
一份自查清单
装完一台机器没数据,按这个顺序过一遍,基本能定位:
systemctl status categraf—— 进程活着吗;journalctl -u categraf | grep -E 'W!|E!|F!'—— 有没有明显报错;conf/config.toml里的两个 url 是不是还是包里自带的示例地址(那个地址对你无效);- 在这台机器上
curl -v <夜莺地址>—— 网络通不通; - 设备列表里有没有这台机器,「更新时间」和「状态」怎么显示;
categraf --configs <绝对路径> --test --inputs <插件>—— 插件本身采得到吗;- 数据查询 → 指标 里查
{agent_hostname="<主机名>"}—— 换个数据源再查一次。
容器部署还有一条:镜像里的 N9E_HOST 环境变量是不生效的(entrypoint 里替换的那个
占位地址在当前的 config.toml 里已经不存在了),必须自己挂载或者改 config.toml。
下一步
- 主机显示无心跳:Categraf 失联
- 数据源连上了但查不到数据:查不到数据
- 写入链路的细节:Remote Write
- 插件配置的细节:输入插件