fluent-bit の lua filter plugin 使用例
概要
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"に変わっています。