3、日志采集与分析:使用Filebeat和Logstash采集搜索引擎日志,通过ELK Stack进行日志分析,定位慢查询和错误日志
搜索引擎跑起来之后,日志就是它的「黑匣子」。
我见过太多团队,线上出了故障,第一反应是「重启试试」。重启完日志一清,啥线索都没了。说实话,这跟销毁犯罪现场没啥区别。
这一章,我们就来聊聊怎么用 Filebeat + Logstash 把搜索引擎的日志乖乖送到 Elasticsearch,再通过 Kibana 把慢查询和错误日志揪出来。
3.1 搜索引擎日志长什么样?
先搞清楚我们要采集什么。搜索引擎的日志,主要分三类:
- 访问日志:记录了每一次搜索请求,包括查询语句、耗时、返回条数、客户端 IP 等。
- 慢查询日志:超过预设阈值的查询会被单独记录下来。我一般把阈值设在 500ms。
- 错误日志:索引损坏、内存溢出、节点宕机……这些信息都在这里。
举个例子,一个典型的搜索引擎访问日志长这样:
2025-03-21 14:23:45.678 [search-thread-12] INFO SearchHandler - query="深度学习" took=123ms hits=45 shards=6/6
这里面藏着很多信息:查询时间、耗时、命中数、分片状态。嗯,每一段都有价值。
3.2 为什么选 Filebeat + Logstash?
你可能要问:直接用 Logstash 采集不行吗?
行,但没必要。Logstash 是 Java 写的,吃内存比较狠。你想想看,搜索引擎本身就已经很吃资源了,再跑个 Logstash 去 tail 日志,简直是雪上加霜。
Filebeat 就轻量多了。它是 Go 写的,占用资源极小。我习惯在每个搜索引擎节点上部署 Filebeat,只负责采集和转发。Logstash 集中部署,负责解析和过滤。
3.3 部署 Filebeat:从日志文件到消息队列
先配置 Filebeat。假设搜索引擎日志在 /var/log/search/search.log:
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/search/*.log
multiline.pattern: '^\d{4}-\d{2}-\d{2}'
multiline.negate: true
multiline.match: after
output.logstash:
hosts: ["logstash.example.com:5044"]
这里有个坑:搜索引擎的异常堆栈是多行的。如果不做 multiline 配置,一行堆栈会被拆成好几条记录,分析起来非常痛苦。
我曾经因为这个原因,排查一个 OOM 问题花了整整两天。后来才发现,堆栈信息被拆散了,根本连不起来。
3.4 Logstash 解析:把日志变成结构化数据
Filebeat 把日志送到 Logstash 后,Logstash 要干三件事:解析、过滤、输出。
先看解析配置:
filter {
grok {
match => { "message" => "%{TIMESTAMP_ISO8601:timestamp} \[%{DATA:thread}\] %{LOGLEVEL:loglevel} %{DATA:class} - query=\"%{DATA:query}\" took=%{NUMBER:duration:float}ms hits=%{NUMBER:hits:int} shards=%{NUMBER:shards_success}/%{NUMBER:shards_total}" }
}
if [loglevel] == "ERROR" {
mutate {
add_tag => ["error_log"]
}
}
if [duration] > 500 {
mutate {
add_tag => ["slow_query"]
}
}
date {
match => ["timestamp", "ISO8601"]
target => "@timestamp"
}
}
你看,我用 grok 把一行文本拆成了十几个字段。这样在 Elasticsearch 里就能直接按 duration 排序,按 loglevel 过滤。
说白了,这一步就是把「天书」变成「表格」。
3.5 在 Kibana 里定位慢查询
数据进了 Elasticsearch,接下来就是 Kibana 的表演时间。
我一般会建两个核心视图:
- 慢查询排行榜:按
duration降序排列,展示查询语句、耗时、命中数。 - 错误日志时间线:按
@timestamp展示 ERROR 级别的日志,看有没有突增。
举个例子,在 Kibana 的 Discover 页面,你可以这样搜:
tags: "slow_query" AND duration > 1000
一秒以上的查询,基本就是「慢查询中的战斗机」了。
我记得有一次,线上搜索突然变慢。打开慢查询排行榜一看,排第一的查询耗时 8 秒。点开一看,查询语句里有个 wildcard 前缀匹配,扫了全索引。嗯,找到元凶了。
3.6 错误日志的告警与聚合
光看还不够,得能告警。Elasticsearch 的 Watcher 或者 ElastAlert 都可以。
我习惯用 ElastAlert,配置简单:
rules:
- name: "搜索引擎错误日志告警"
type: frequency
index: search-logs-*
timeframe:
minutes: 5
num_events: 10
filter:
- term:
tags: "error_log"
alert:
- "slack"
- "email"
slack_webhook_url: "https://hooks.slack.com/xxx"
这个规则的意思是:5 分钟内出现 10 条以上错误日志,就发 Slack 通知。
为什么要设阈值?因为搜索引擎偶尔会有一些可恢复的错误,比如单个分片查询超时重试。如果每条都告警,你会被「告警疲劳」淹没的。
3.7 避坑指南
最后,分享几个我踩过的坑:
- 时区问题:Filebeat 默认用 UTC,搜索引擎日志可能是本地时间。记得在 Logstash 里用
date插件统一时区。 - 日志轮转:搜索引擎日志一般会按天或按大小轮转。Filebeat 的
close_inactive参数要设得合理,不然轮转后 Filebeat 还占着文件句柄。 - 索引生命周期:搜索引擎日志量很大,一天几十 GB 很正常。记得配 ILM(索引生命周期管理),超过 30 天的数据自动删除或归档。
嗯,这一章的内容就到这里。日志采集和分析做好了,搜索引擎的「黑匣子」就不再是秘密了。