fluentd で LTSV なログを BigQuery に送るときの注意点 その2
前回の記事で、
LTSV -> fluentd -> BigQuery という構成時、 BigQuery に boolean が正しく格納されない問題がある、と書きました。
この問題に対し、 @yukiyan_w さんが以下の様なサンプルコードを教えてくださいました。
これで動いたので貼っときますね https://t.co/Vv426HFrsx / “fluentd で LTSV なログを BigQuery に送るときの注意点 - はのちゃ爆発” https://t.co/h1V20DF1UT
— Yukiyan (@yukiyan_w) July 31, 2016
また、サンプル以外でも以下の様なつぶやきがあったので、色々調べつつやってみました。
in_tail使ってるならtypes使えば良いが...
— Yukiyan (@yukiyan_w) July 31, 2016
起こっていた問題と解決方法
今回、以下の様なsourceディレクティブを設定して処理を行っていました。(一部改変)
<source> @type tail format ltsv time_format %Y-%m-%dT%H:%M:%S %z path /var/www/hoge.log pos_file /var/log/td-agent/hoge.log tag hoge.fuga </source>
上記のsourceは、booleanが正しくBigQueryに格納されない時のものです。
このsourceに対し、以下のオプションを追加します。
types is_awesome:bool
ログにis_awesomeという項目がある、という前提です。
types?
types って何やねんという感じですよね。公式サイトの説明は以下。
今回は@typeがtailなので、tail Input Pluginを見ています。
types (optional)
Although every parsed field has type string by default, you can specify other types.
typesを指定しないとデフォルトのstringでパースされます、と。
typesを指定すれば別の型を指定することが可能に。
The syntax is
types <field_name_1>:<type_name_1>,<field_name_2>:<type_name_2>,... e.g.,
types user_id:integer,paid:bool,paid_usd_amount:float
フィールド名: 型という形式で指定します。カンマで区切って複数指定も可能。
Unspecified fields are parsed at the default string type.
不明な型を指定した場合はstringとして解釈されるとのこと。
使用できる型は以下の通り。intは使えずintegerなことに注意。
string bool integer (“int” would NOT work!) float time array
array と time に関しては別の扱い方が出来たりするみたいだけど、今は省略します。
json and none parsers don’t support types parameter.
あと、パーサがjson、noneの場合はtypesが効かないので注意、とのこと。
まとめ
今回、以下の様な構成で fluentd から BigQuery にデータを送っていました。
System -> LTSV log -> fluentd(tail, fluent-plugin-bigquery) -> BigQuery
fluentd のtail Input Plugin を使って読み込まれるデータは、デフォルトでは文字列でパースされます。
実際に BigQuery にデータを送信する際のスキーマファイル内でbooleanを指定していても、その手前、
ソースからデータを読み込んでパースする部分で、すべて文字列としてパースされてしまいました。
今回のトラブルは、パースされたtrueやfalseなどの文字列を boolean に変換しようとした結果、
全て true に変換されてしまっていたのが原因でした。
こうした事態を防ぐため、types オプションを source ディレクティブ内に記述しました。
これによって、ログファイルの指定フィールドを、きちんとbooleanとしてパースさせることが出来るようになりました。
fluentd について扱っている記事で、typesについて触れているものは見かけた記憶があまりありませんでした。
あんまりこの辺で引っかかることはないんでしょうか…?