EmbulkのFilterプラグイン「embulk-filter-insert」を本日リリースしました。Filterプラグインと言いつつ、このプラグインを適用してもレコードは減らず、むしろカラムが増えます。Rubygemsで公開済みのため、インストールは以下のコマンド一発です。
$ embulk gem install embulk-filter-insert
このプラグインのインストール後に、例えば設定ファイルに
filters: - type: insert columns: - host: host01 - service: service01 at: top
と書くと、読み込んだレコードすべての先頭に、カラムが2個追加されます。カラムに含まれる値は固定値(この例では文字列"host01"と"service01")です。
ソースコードに興味のある方は muziyoshiz/embulk-filter-insert をどうぞ。
一体どうしてこんなプラグインを?
Embulkを使って突貫でデータを取り込もうとしたときに、ホスト名やログの種別を固定で付けたいことが、過去に何度かありました。例えば、Input Fileプラグインを使って myapp.log.2015-06-25.gz みたいなファイルを、あちこちのサーバから読み込むようなケースです。
いままでは、そのようなカラムの挿入処理をparserプラグインのなかに埋め込んでしまっていたのですが、再利用性を考えてFilterプラグインに切り出しました。インストールしておくと、たまに便利な場面があると思います。
Fluentdにも似たようなプラグインありませんでしたっけ?
@repeatedlyさんが公開してるfluent-plugin-record-modifierですね。僕は使ったことがないのですが、設定ファイルに
<filter pattern> type record_modifier gen_host ${hostname} foo bar </filter>
のように記載すれば任意のkey-value pairを追加できて、
<filter pattern> type record_modifier # remove key1 and key2 keys from record remove_keys key1,key2 </filter>
のように記載すれば、指定したkeyの削除もできるみたいです。
ただ、EmbulkがFluentdと違うところとして、カラムの順序が重要なことと、型定義が必要なことがあります。
1. カラムの順序が重要
Embulkのinputプラグインで取り込んだデータは、配列としてparserプラグインやoutputプラグインに渡されます。そのため、例えば独自のparserプラグインを書いたあとで、大本のデータのカラムの順序が変わったりすると、(普通に書いてると)parserプラグインが動かなくなったりします。
また、この並び順は、最終的に人間がデータを見るときの並び順にもなります(output fileプラグインの場合など)。
そのため、カラムの挿入位置は、後続のプラグインや、見た目のことを考慮して変更できたほうが、色々便利そうです。
2. 型定義が必要
Fluentdの場合と違って、Embulkのカラムには型があるので、カラムを挿入するFilterプラグインには、挿入したいカラム名と値に加えて、型の情報も与える必要があります。かといって、挿入したい値を{ name: service, value: service01, type: string }
のように書くのも冗長でめんどくさいし……。
そんなわけで、上記の情報を設定ファイルに書くことができて、なおかつ設定が自然文に見えてわかりやすくなるように、今回は挿入のみの単機能のプラグインとして実装しました。
例えば、カラムの順序と型定義を明示すると、以下のような感じになります。末尾に挿入する場合は順序(at)を、文字列を挿入する場合は型定義(as)をそれぞれ省略できます。
filters: - { type: insert, column: { user_id: 1234567, as: long }, at: top }
余談
embulk-filter-insertと対になるプラグインとして、embulk-filter-removeプラグインというのも考えていました。以下のような設定で、指定したカラムを削除できるプラグインです。
filters: - { type: remove, column: user_id }
しかし、Ingressのイベントに参加するために仙台行ったりしてモタモタしてるうちに、@sonotsさんがsonots/embulk-filter-columnされていて、出遅れた感が……。
あと、前回のparserプラグインやらfilterプラグインを書いていて疑問だったのですが、プラグインのテストってどう書くのが流儀なんですかね。誰か知ってたら教えてください。