Fluent Bit 中如何截断超长的日志消息?

Fluent Bit 截断超长日志最灵活的方式是用 Lua filter 写脚本按长度截断字段。本文给出 truncate.lua 示例和 Fluent Bit 配置,以及观测云 Pipeline 的等价做法。

最佳实践
Fluent Bit 中如何截断超长的日志消息?封面

最通用的做法:写一个 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,收到的仍是截断内容。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台