クロスプラットフォームで動作し、オープンソースであるデータ収集ソフトウェアとしてFluentdがあります。 Fluentdはさまざまな用途にあわせてプラグインにより機能を拡張できます。 多くのプラグインが開発されているのは、要件を満たすべく新規にプラグインが開発される事例があるためです。
Fluentdで収集したログは、Fluentd内部ではイベントという形で処理されます。 イベントはタグと日時、レコードから構成され、収集されたデータはレコードに詰め込まれます。
発生したログをアーカイブ目的のため手を加えずになんらかの外部サービスに保存するだけということもありますが、 レコードに詰め込まれたデータの加工が必要となる場合が多々あります。
Fluentdでは非常に多くのプラグインが開発されてきているので、レコードを分割するという目的だけでも専用のものがいくつかあります。 今回はそのようなプラグインの中から、Fluentdサポートの一環として、お客様の要望に応じて新規でプラグインを開発した事例を紹介します。
新規プラグインの開発のきっかけ
すでに言及したように、クリアコードではFluentdサポートを提供しています。
このサービスでは技術サポートとして、エラー時のソースコードレベルの解析のみならず、お客様の要望に応じて既存のプラグインの修正や、場合によっては新規に開発を行うこともあります。
ご相談いただいた事例では、フィルタやラベルの設定を駆使し、record_modifier
でレコードを加工するやりかたを検討されていたようです。
しかし、それによってFluentdの設定が複雑化し、メンテナンスの継続性に難があったことからその方法は不採用となり、お困りのため弊社に相談がありました。
実現したかった加工の例
要望頂いていたのは、次のような入力があった場合に、レコードを分割するフィルタ処理を実現することでした。
入力例:
{"key1":"value1", "key2":"value2", "message":[ "v1", "v2", "v3"] }
期待する加工後の出力:
{"key1":"value1", "key2":"value2", "message": "v1"}
{"key1":"value1", "key2":"value2", "message": "v2"}
{"key1":"value1", "key2":"value2", "message": "v3"}
必要なのは、指定したフィールドの値(配列)を分割し、それ以外のフィールドはそのまま維持しつつ新しくレコードを生成するという振る舞いです。
既存のプラグインの機能比較
レコードを分割するという観点でも多種多様なプラグインがあります。 既存のプラグインで同様のことができないか確認してみました。 既存のプラグインを機能面で比較すると次のとおりです。
プラグイン | 種類 | 分割対象 | 分割方法 | フィールド維持 | フィールド削除 | テスト | CI |
---|---|---|---|---|---|---|---|
fluent-plugin-split | output | 文字列 | 区切り文字(カンマもしくはスペース) | ✗ | ✗ | ○ | ✗ |
fluent-plugin-split-event | filter | 文字列 | 区切り文字(任意) | ✗ | ✗ | ○ | ✗ |
fluent-plugin-filter-split-message | filter | 文字列 | 区切り文字(任意) | ✗ | ✗ | ○ | ○ |
fluent-plugin-split_record | filter | 文字列 | スペース区切りのkey=value or 正規表現 | ○ | ✗ | ○ | ✗ |
fluent-plugin-record-splitter | output | 文字列 | 改行 or 正規表現 | ○ | ○ | ○ | ○ |
fluent-plugin-split-array | filter | ハッシュの配列 | ハッシュごと | ✗ | ✗ | ○ | ✗ |
fluent-plugin-record_splitter | output | ハッシュの配列 | ハッシュごと | ○ | ✗ | ○ | ✗ |
- 種類: プラグインの種別を示す
- 分割対象: プラグインが分割できるデータ形式
- 分割方法: 分割する単位。
- フィールド維持: 分割対象であるフィールド以外のフィールドとその値を維持する対象を指定する機能があるかを示します。
- フィールド削除: 分割対象であるフィールド以外のフィールドとその値を削除する対象を指定する機能があるかを示します。
- テスト: specやtest-unitなどのテストが整備されているかを示す
- CI: GitHub Actionsによる継続的なテストのしくみがあるかを示す
前提条件として、フィールドの値が文字列の配列であるものを分割して新規レコードを生成できるfilterプラグインが必要でした。
既存のプラグインでは残念ながら、すべての条件を満たすものはありませんでした。 比較的近い機能も有するものでも、次のような課題があり選択肢から外れました。
- fluent-plugin-split-arrayには値の配列を分割する機能と、既存のフィールドを保持する機能がない。メンテナンスが活発でない。
- fluent-plugin-record_splitterは値の配列の分割をする機能がなく、分割を想定されているレコード形式がかなり限定されている。メンテナンスが活発でない。
この手の操作を実現するには、昨今ではfilter
プラグインとして実装するのが定石です。
そのため、output
プラグインとして実装されていたり1、あまりメンテンナンスが活発でないものは、継続性に懸念があり選択肢からはずしました。
新規開発したプラグイン
既存のプラグインでは要望を満たすことができなかったため、新規プラグインを開発しました。 それが fluent-plugin-filter-splitです。
プラグイン | 種類 | 分割対象 | 分割方法 | フィールド維持 | フィールド削除 | テスト | CI |
---|---|---|---|---|---|---|---|
fluent-plugin-filter-split | filter | 値の配列 | 値ごと | ○ | ○ | ○ | ○ |
次のようにfilterプラグインを利用設定をすることで、前述の通りにレコードを分割することができます。
<source>
@type tail
tag test
path sample.log
read_from_head true
<parse>
@type json
</parse>
</source>
<filter test>
@type filter_split
split_key message
keep_other_key true
</filter>
<match test>
@type stdout
</match>
おわりに
今回はFluentdサポートの一環として、お客様の要望に応じて新規でプラグインを開発した事例を紹介しました。
クリアコードはFluentdのサポートサービスを行っています。 Fluent Packageへのアップデート支援や影響のあるバグ・脆弱性のレポートなどのサポートだけでなく、 お客様の要望に応じて新規プラグインの開発も行っています。fluent-plugin-filter-splitはお客様の要望に応えるかたちで開発し、 了承のもとApache 2.0のライセンスで公開した成果物です。
詳しくはFluentdのサポートサービスをご覧いただき、お問い合わせフォームよりお気軽にお問い合わせください。
-
Fluentdの
filter
プラグイン機能はv0.12で導入されたため、output
プラグインとして実装されているものはそのときから更新されていないと判断できる。 ↩