3. 日志数据采集:日志文件格式解析与采集实战
日志采集,说白了就是运维机器人的「耳朵」。耳朵不好使,后面分析得再漂亮也是白搭。今天咱们就聊聊日志文件那点事儿,以及怎么用 Filebeat 和 Logstash 这对黄金搭档把数据稳稳地收上来。
3.1 日志文件格式解析
我刚开始做运维那会儿,最头疼的就是日志格式五花八门。有的系统吐 JSON,有的吐 CSV,还有的能把多行日志挤在一行里。你想想看,如果连格式都搞不清楚,后面怎么玩?
3.1.1 JSON 格式日志
JSON 格式现在最流行,因为它自带结构。每个字段都有名字,解析起来特别方便。我个人习惯在生产环境里优先推荐 JSON 格式,省心。
{
"timestamp": "2024-01-15T10:30:00.123Z",
"level": "ERROR",
"service": "user-service",
"message": "数据库连接超时",
"request_id": "req-abc-123",
"duration_ms": 5000
}
嗯,这里要注意:JSON 日志虽然好,但字段嵌套太深会拖慢解析速度。我建议最多嵌套两层,再深就该考虑扁平化了。
3.1.2 CSV 格式日志
CSV 格式比较老派,但很多遗留系统还在用。它的优点是体积小,缺点是字段顺序不能乱。
timestamp,level,service,message,duration_ms
2024-01-15T10:30:00.123Z,ERROR,user-service,数据库连接超时,5000
我在项目中遇到过一个问题:CSV 里的某个字段值本身带了逗号,结果解析出来全乱了。后来我们统一要求所有字段用双引号包裹,才算解决。
3.1.3 多行日志
多行日志是最坑的。比如 Java 的异常堆栈,一个错误能吐十几行。如果按行采集,一个完整的错误就被拆得七零八落。
2024-01-15 10:30:00.123 ERROR [user-service] 数据库连接超时
java.sql.SQLTimeoutException: 等待超时
at com.mysql.jdbc.ConnectionImpl.connect(ConnectionImpl.java:123)
at com.zaxxer.hikari.pool.PoolBase.connect(PoolBase.java:456)
... 5 more
我曾经因为没处理好这个,排查问题时对着散落的日志行看了两个小时,最后发现是同一个错误。从那以后,我处理多行日志就格外小心。
3.2 使用 Filebeat 进行日志采集
Filebeat 是 Elastic 家的轻量级采集器。它体积小、资源占用低,适合部署在每台服务器上。说白了,它就是你的「前线侦察兵」。
3.2.1 安装与配置
安装 Filebeat 很简单,一条命令搞定。但配置才是重头戏。
# filebeat.yml 核心配置
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/app/*.log
# 多行日志处理
multiline:
pattern: '^\d{4}-\d{2}-\d{2}'
negate: true
match: after
output.elasticsearch:
hosts: ["localhost:9200"]
这里我重点说一下 multiline 配置。pattern 写的是时间戳的正则,意思是「以日期开头的行才是新日志的开始」。negate: true 表示「不符合这个模式的行」,match: after 表示「把这些行合并到上一行后面」。你看,逻辑其实很简单。
3.2.2 实战中的坑
clean_removed: true 和 clean_inactive: 72h。
3.3 Logstash 数据预处理
Filebeat 负责采集,Logstash 负责「洗数据」。为什么需要洗?因为原始日志往往很糙,字段名不规范、时间格式不统一、有些字段需要拆分或合并。
3.3.1 核心处理流程
Logstash 的处理流程是经典的「输入 → 过滤 → 输出」管道。我画了一张图,帮你理解这个逻辑。
3.3.2 常用过滤插件
过滤插件是 Logstash 的灵魂。我挑几个最常用的说说。
| 插件名 | 作用 | 我常用的场景 |
|---|---|---|
| grok | 正则解析非结构化文本 | 解析 Apache/Nginx 访问日志 |
| mutate | 字段增删改、类型转换 | 把字符串数字转成整数 |
| date | 时间格式标准化 | 把各种奇葩时间格式转成 ISO 8601 |
| geoip | IP 地址转地理位置 | 分析用户来源地域 |
3.3.3 实战配置示例
下面这个配置,是我在一个电商项目里用过的。它处理的是 Nginx 访问日志,同时做了 IP 地理定位和时间标准化。
input {
beats {
port => 5044
}
}
filter {
# 解析 Nginx 日志
grok {
match => { "message" => "%{COMBINEDAPACHELOG}" }
}
# 时间标准化
date {
match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
target => "@timestamp"
}
# IP 地理定位
geoip {
source => "clientip"
target => "geo"
}
# 字段清理
mutate {
remove_field => ["message", "path"]
convert => { "response" => "integer" }
}
}
output {
elasticsearch {
hosts => ["localhost:9200"]
index => "nginx-access-%{+YYYY.MM.dd}"
}
}
3.4 整体架构串联
最后,我把这三个组件串起来,看看它们是怎么协同工作的。
你看,整个链路其实不复杂。Filebeat 负责「搬砖」,Logstash 负责「精加工」,Elasticsearch 负责「存储」。各司其职,配合默契。
好了,日志采集这块就聊到这儿。记住一句话:采集是基础,格式是门槛,预处理是灵魂。把这三样搞定了,后面的分析工作才能顺风顺水。