TL;DR
ラベルを指定した場合のエミット先はプラグインの実装によって異なる。
- ラベルに対応していないプラグインの場合
-
@label
の有無に関わらずトップにエミットする
-
- ラベルに対応しているプラグインの場合
-
@label
を設定している場合、対応するlabelタグにエミットする -
@label
を設定していない場合、自分のいるlabelタグに再エミットする
-
<label>
タグ内で<match>
タグとパターンがマッチしなかったイベントについては、トップでマッチしなかった場合と同様警告がでる。
環境
動作は以下のバージョンで確認した。
-
td-agent (2.3.5-1)
- fluentd (0.12.36)
-
fluent-plugin-rewrite-tag-filter (1.5.1, 1.5.2)
-
fluent-plugin-flowcounter (0.3.0)
ラベルに対応していないプラグインの挙動
ラベルが実装されたのがfluentd 0.12なので、まだラベルに対応していないプラグインも多い。
未対応のプラグインでは以下の記事で説明されているようにEngine.emit
でエミットが行われている(対応しているプラグインではEngine.emit
の代わりにrouter.emit
が使われている)。
Fluentd v0.12 ラベル機能の使い方とプラグインの改修方法 - Qiita
ラベルに対応していないプラグインは、@label
の有無に関わらず常にトップにエミットする。
例としてrewrite_tag_filter (1.5.1)の動きを見てみる。(rewrite_tag_filterは1.5.2でラベルに対応しています。以下のrewrite_tag_filterの挙動は例としてお読みください。)
動作確認用に次のような設定ファイルを用意する。
rewrite_tag_filterでラベルを@labeled
と指定し、ラベルが@labeled
になっていれば<label @labeled>
にエミットされlabeled true
がレコードに追加されて出力される。ラベルが無視されトップにエミットされている場合には、labeled false
がレコードに追加されて出力される。
<source>
@type forward
@label @test
</source>
<label @test>
<filter>
@type stdout
</filter>
<match>
@type rewrite_tag_filter
@label @labeled
rewriterule1 value .* rewritten
</match>
</label>
<label @labeled>
<filter>
@type record_transformer
<record>
labeled true
</record>
</filter>
<match>
type stdout
</match>
</label>
<filter>
@type record_transformer
<record>
labeled false
</record>
</filter>
<match>
type stdout
</match>
上記の設定ファイルでfluentdを起動し、fluent-catでテスト用のデータを読み込ませる。
$ fluentd -c rewrite_tag_filter.conf -vv --use-v1-config &
$ echo "{\"value\": \"test\"}" | fluent-cat test
結果は以下のように"labeled":"false"
になっており、ラベル@labeled
は無視されていることがわかる。(出力は見易さのためタイムスタンプを消すなど加工しています。)
rewritten: {"value":"test","labeled":"false"}
1.5.2以降ではラベルが有効で以下のように"labeled":"true"
となります。
rewritten: {"value":"test","labeled":"true"}
ラベルに対応しているプラグインの挙動
ラベルに対応しているプラグインでは当然でラベルを指定すれば対応するラベルへ飛ぶ。
ラベルを指定していない場合には、自分のいるラベルへ再エミットされる。
relabel
まず、例としてrelabelプラグインの挙動を見てみる。
<source>
@type forward
@label @test
</source>
<label @test>
<filter>
@type stdout
</filter>
<match>
@type relabel
</match>
</label>
<label @labeled>
<filter>
@type record_transformer
<record>
labeled true
</record>
</filter>
<match>
type stdout
</match>
</label>
<filter>
@type record_transformer
<record>
labeled false
</record>
</filter>
<match>
type stdout
</match>
fluentdを起動しテスト用のデータを読み込ませる。
$ fluentd -c relabel.conf -vv --use-v1-config &
$ echo "{\"value\": \"test\"}" | fluent-cat test
結果は次のような出力が延々と繰り返される。これはrelabelの出力が再度<label @test>
にエミットされループしているためである。
test: {"value":"test"}
test: {"value":"test"}
test: {"value":"test"}
test: {"value":"test"}
...
flowcounter
flowcounterもラベルを指定しなかった場合には自分のいるラベルへ再エミットされる。
まず正しい動作を確認するためにラベルを指定した場合の動きを見てみる。
<source>
@type forward
@label @test
</source>
<label @test>
<filter>
@type stdout
</filter>
<match>
@type flowcounter
@label @labeled
count_keys *
unit second
</match>
</label>
<label @labeled>
<filter>
@type record_transformer
<record>
labeled true
</record>
</filter>
<match>
type stdout
</match>
</label>
<filter>
@type record_transformer
<record>
labeled false
</record>
</filter>
<match>
type stdout
</match>
ラベルを指定している場合にはfluentdを起動すると、flowcount: {"labeled":"true"}
が1秒毎に出力される。"labeled":"true"
が付いていることから<label @labeled>
内から出力されていることがわかる。
$ fluentd -c flowcounter.conf -vv --use-v1-config &
flowcount: {"labeled":"true"}
flowcount: {"labeled":"true"}
flowcount: {"labeled":"true"}
...
この状態でデータを入力するとカウントされる。testタグをつけているのでキーの頭にtest_
が付けられている。
$ echo "{\"value\": \"test\"}" | fluent-cat test
flowcount: {"test_count":1,"test_bytes":12,"test_count_rate":1.0,"test_bytes_rate":12.0,"labeled":"true"}
flowcount: {"test_count":0,"test_bytes":0,"test_count_rate":0.0,"test_bytes_rate":0.0,"labeled":"true"}
flowcount: {"test_count":0,"test_bytes":0,"test_count_rate":0.0,"test_bytes_rate":0.0,"labeled":"true"}
flowcount: {"test_count":0,"test_bytes":0,"test_count_rate":0.0,"test_bytes_rate":0.0,"labeled":"true"}
...
次に、ラベルの指定をコメントアウトしてfluentdを再起動してみる。
<label @test>
<filter>
@type stdout
</filter>
<match>
@type flowcounter
# @label @labeled
count_keys *
unit second
</match>
</label>
再起動すると何も入力しなくても次のようにカウント結果が表示される。キー名の頭がflowcount_
になっていることからflowcounterの出力が<label @test>
に再エミットされ自分自身の出力をカウントしていることがわかる。
1回データを入力しただけで大量の出力が発生するrelabelのケースと異なり、1秒毎にしか出力されないので、結果をログで見ていてもループしていることに気づきにくい。
flowcount: {}
flowcount: {"flowcount_count":1,"flowcount_bytes":1,"flowcount_count_rate":1.0,"flowcount_bytes_rate":1.0}
flowcount: {"flowcount_count":1,"flowcount_bytes":95,"flowcount_count_rate":1.0,"flowcount_bytes_rate":95.0}
flowcount: {"flowcount_count":1,"flowcount_bytes":95,"flowcount_count_rate":1.0,"flowcount_bytes_rate":95.0}
flowcount: {"flowcount_count":1,"flowcount_bytes":95,"flowcount_count_rate":1.0,"flowcount_bytes_rate":95.0}
flowcount: {"flowcount_count":1,"flowcount_bytes":95,"flowcount_count_rate":1.0,"flowcount_bytes_rate":95.0}
...
この状態でデータを入力すると、以下のように入力されたデータについてがカウントされる。
$ echo "{\"value\": \"test\"}" | fluent-cat test
flowcount: {"flowcount_count":1,"flowcount_bytes":95,"test_count":1,"test_bytes":12,"flowcount_count_rate":1.0,"flowcount_bytes_rate":95.0,"test_count_rate":1.0,"test_bytes_rate":12.0}
flowcount: {"flowcount_count":1,"flowcount_bytes":169,"test_count":0,"test_bytes":0,"flowcount_count_rate":1.0,"flowcount_bytes_rate":169.0,"test_count_rate":0.0,"test_bytes_rate":0.0}
flowcount: {"flowcount_count":1,"flowcount_bytes":170,"test_count":0,"test_bytes":0,"flowcount_count_rate":1.0,"flowcount_bytes_rate":170.0,"test_count_rate":0.0,"test_bytes_rate":0.0}
flowcount: {"flowcount_count":1,"flowcount_bytes":170,"test_count":0,"test_bytes":0,"flowcount_count_rate":1.0,"flowcount_bytes_rate":170.0,"test_count_rate":0.0,"test_bytes_rate":0.0}
...
<label>
タグ内で<match>
とパターンがマッチしなかった場合
<label @test>
から<match>
タグを削除し、パターンがマッチしなかった場合の挙動をみる。
<source>
@type forward
@label @test
</source>
<label @test>
<filter>
@type stdout
</filter>
</label>
<label @labeled>
<filter>
@type record_transformer
<record>
labeled true
</record>
</filter>
<match>
type stdout
</match>
</label>
<filter>
@type record_transformer
<record>
labeled false
</record>
</filter>
<match>
type stdout
</match>
<label @ERROR>
<filter>
@type record_transformer
<record>
error true
</record>
</filter>
<match>
type stdout
</match>
</label>
fluentdを起動しデータを入力すると、no patterns matched tag="test"
という警告がでる。fluentタグの出力に"labeled":"false"
が付いていることからfluentタグはラベル内ではなくトップに出力されていることがわかる。
$ fluentd -c no_match.conf -vv --use-v1-config &
$ echo "{\"value\": \"test\"}" | fluent-cat test
[trace]: plugin/in_forward.rb:194:initialize: accepted fluent socket from '127.0.0.1:53776': object_id=70322129696080
test: {"value":"test"}
[warn]: fluent/agent.rb:164:emit: no patterns matched tag="test"
[trace]: plugin/in_forward.rb:262:on_close: closed socket
fluent.trace: {"message":"accepted fluent socket from '127.0.0.1:53776': object_id=70322129696080","labeled":"false"}
fluent.warn: {"tag":"test","message":"no patterns matched tag=\"test\"","labeled":"false"}
fluent.trace: {"message":"closed socket","labeled":"false"}