fluent-bit の lua filter plugin 使用例

概要

fluentbit.io

fluent-bit には Lua スクリプトでfilterできるプラグインがあります。 これを使うと、下記のようなことができます。

  • recordに情報を追加する
  • 特定の条件にマッチしたrecordをフィルタする
  • record内の特定の情報を削除する

目次

使用方法

fluent-bitにはLuaスクリプトのパスと、スクリプトに記載されている関数名を伝える必要があります。 たとえば、下記の例は、test.luaスクリプトをロードし、そこに含まれるtest_func関数を実行するという意味になります。

[INPUT]
    Name dummy
    Tag  test
    Dummy  {"foo":"bar"}

[FILTER]
    Name   lua
    Match  *
    script ./test.lua
    call   test_func

[OUTPUT]
    Name  stdout
    Match *

制約

Fluent-bitのLuaは数値型としてdoubleを使用しています。 そのため、下記のような問題が発生する可能性があります。

前者については、Type_int_key というプロパティを指定することで、フィルタ後の値を再度整数型に変更してくれるようになります。

Lua - Fluent Bit: Official Manual

後者については、良い解が思いついていません。パッチをお待ちしております。

Lua filters can mangle timestamps · Issue #2015 · fluent/fluent-bit · GitHub

luaスクリプト側の仕様

下記のように引数と戻り値がそれぞれ3つずつ必要です。

function test_func(tag, timestamp, record)
     -- something to do
    return ret, timestamp, new_record
end

fluentdのeventを構成するtag, timestampとLua連想配列形式のrecordが与えられ、戻り値としてfilter結果を示すretとtimestamp、そしてrecordを返却します。 ここで、retはfilter結果に応じて、下記のいずれかを返す必要があります。

filter結果 retの値 備考
削除した -1 不要なeventをフィルタリングする用途
何も変更しなかった 0
recordとtimestampを変更した 1
recordのみ変更した 2 v1.4.3より対応。timestampの丸め誤差を防止するための機能。

使用例

それでは使用例を紹介していきます。

時刻情報をrecordに加える

フィルタした時刻を保持したい場合には下記のように行います。

configuration

test.lua:

function test_func(tag, timestamp, record)
    new_record = record
    new_record["filterd_time"] = os.time()
    new_record["filterd_date"] = os.date()
    return 2, timestamp, new_record
end

input

{"foo"=>"bar"}

output

{"filterd_date"=>"Sun May 31 09:10:59 2020", "foo"=>"bar", "filterd_time"=>1590883859.000000}

タグをrecordに加える

tagというkey名でtagの文字列を追加するスクリプトです。

configuration

test.lua:

function test_func(tag, timestamp, record)
    new_record = record
    new_record["tag"] = tag
    return 2, timestamp, new_record
end

test.conf:

[INPUT]
    Name dummy
    Tag  test
    Dummy  {"foo":"bar"}

[FILTER]
    Name   lua
    Match  *
    script ./test.lua
    call   test_func

[OUTPUT]
    Name  stdout
    Match *

input

{"foo"=>"bar"}

output

{"foo"=>"bar", "tag"=>"test"}

"tag"=>"test" が付与されています。

特定のkey/value ペアを削除する

record内の一部ペアを消去する例です。

configuration

test.conf:

[INPUT]
    Name dummy
    Tag  test
    Dummy  {"important":"value", "drop":"value"}

[FILTER]
    Name   lua
    Match  *
    script ./test.lua
    call   test_func

[OUTPUT]
    Name  stdout
    Match *

test.lua:

function test_func(tag, timestamp, record)
     if record["drop"] == nil then
        return 0, timestamp, record
     end
     new_record = record
     new_record["drop"] = nil
     return 2, timestamp, new_record
end

input

{"important"=>"value", "drop"=>"value"}

output

{"important"=>"value"}

"drop":"value" というペアが消えています。

特定のkeyを含むrecordを捨ててフィルタする

例えば不要なデータ通信を行わないように、record内に特定のkeyが含まれていた場合にそのrecord全体を捨てるユースケースがあるかと思います。

下記は、"drop" というkeyが含まれている場合にrecord全体を捨てる例になります。

configuration

[INPUT]
    Name dummy
    Tag  test
    Dummy  {"important":"value"}

[INPUT]
    Name dummy
    Tag  test
    Dummy  {"drop":true}

[FILTER]
    Name   lua
    Match  *
    script ./test.lua
    call   test_func

[OUTPUT]
    Name  stdout
    Match *

test.lua:

function test_func(tag, timestamp, record)
     key = "drop"
     if record[key] ~= nil then
        return -1, timestamp, record
     end
     return 0, timestamp, record
end

input

{"important"=>"value"}
{"drop"=>true}

output

{"important"=>"value"}

{"drop":true} というrecordが出力されなくなるかと思います。

特定のkey名を変更する

configuration

test.conf

[INPUT]
    Name dummy
    Tag  test
    Dummy  {"foo":"bar"}

[FILTER]
    Name   lua
    Match  *
    script ./test.lua
    call   test_func

[OUTPUT]
    Name  stdout
    Match *

test.lua:

function test_func(tag, timestamp, record)
     new_record = record
     if record["foo"] == nil then
        return 0, timestamp, new_record
     end
     new_record["hoge"] = record["foo"]
     new_record["foo"] = nil
     return 2, timestamp, new_record
end

input

{"foo"=>"bar"}

output

{"hoge"=>"bar"}

"foo"というkeyが"hoge"に変わっています。