Fluent Bit 中如何截断超长的日志消息?
Fluent Bit 截断超长日志最灵活的方式是用 Lua filter 写脚本按长度截断字段。本文给出 truncate.lua 示例和 Fluent Bit 配置,以及观测云 Pipeline 的等价做法。
最通用的做法:写一个 Lua 脚本(如 truncate.lua)检查目标字段长度,超长则截断,然后在 Fluent Bit 配置中通过 Lua filter 挂载该脚本。
完整配置
Lua 脚本 truncate.lua:
function truncate_msg(tag, timestamp, record)
local max_length = 1000 -- 字节,不是字符
local marker = "...[truncated]"
if type(record.msg) == "string" and #record.msg > max_length then
local n = max_length - #marker
-- 假定输入为有效 UTF-8;避免在多字节字符中间截断
while n > 0 do
local b = string.byte(record.msg, n + 1)
if b < 128 or b >= 192 then break end
n = n - 1
end
record.msg = string.sub(record.msg, 1, n) .. marker
return 2, timestamp, record
end
return 0, timestamp, record
end
Fluent Bit 配置:
[INPUT]
Name tail
Path /var/log/myapp/*.log
Tag myapp.*
Key msg
[FILTER]
Name lua
Match myapp.*
script /etc/fluent-bit/truncate.lua
call truncate_msg
[OUTPUT]
Name stdout
Match myapp.*
Lua filter 的返回约定:2 表示只修改 record 并保留原时间戳;0 表示不变,1 才表示同时使用返回的时间戳。Tail 默认字段通常为 log,这里显式设为 msg。
为什么不用 Logstash 的 truncate
Lua 适合按字段实现自定义截断;不同版本和 input 也可能提供长行限制选项,但跳过/限制输入行与字段截断不是同一语义。
常见问题(FAQ)
Q:为什么要截断日志?
A:超长日志(如几 MB 的请求 body、完整 SQL 语句)会消耗存储和网络带宽、拖慢检索。通常只留前几百到几千字符用于排查。
Q:多个字段都要截断?
A:在 Lua 函数里对每个字段重复判断即可,或写个循环遍历指定字段列表。
Q:截断会影响日志原文吗?
A:Fluent Bit 管道内的修改是单向的,输出侧看到的就是截断后的内容。如果需要保留原文,应在修改前复制到独立管道或归档;在该 filter 之后增加另一个 output,收到的仍是截断内容。