はのちゃ爆発

はのちゃが技術ネタとか日常のこととかを書いてます。

fluentd で LTSV なログを BigQuery に送るときの注意点 その2

前回の記事で、 LTSV -> fluentd -> BigQuery という構成時、 BigQuery に boolean が正しく格納されない問題がある、と書きました。

この問題に対し、 @yukiyan_w さんが以下の様なサンプルコードを教えてくださいました。

また、サンプル以外でも以下の様なつぶやきがあったので、色々調べつつやってみました。

起こっていた問題と解決方法

今回、以下の様な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 って何やねんという感じですよね。公式サイトの説明は以下。 今回は@typetailなので、tail Input Pluginを見ています。

docs.fluentd.org

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

arraytime に関しては別の扱い方が出来たりするみたいだけど、今は省略します。

json and none parsers don’t support types parameter.

あと、パーサがjsonnoneの場合はtypesが効かないので注意、とのこと。

まとめ

今回、以下の様な構成で fluentd から BigQuery にデータを送っていました。

System -> LTSV log -> fluentd(tail, fluent-plugin-bigquery) -> BigQuery

fluentd のtail Input Plugin を使って読み込まれるデータは、デフォルトでは文字列でパースされます。

実際に BigQuery にデータを送信する際のスキーマファイル内でbooleanを指定していても、その手前、 ソースからデータを読み込んでパースする部分で、すべて文字列としてパースされてしまいました。

今回のトラブルは、パースされたtruefalseなどの文字列を boolean に変換しようとした結果、 全て true に変換されてしまっていたのが原因でした。

こうした事態を防ぐため、types オプションを source ディレクティブ内に記述しました。 これによって、ログファイルの指定フィールドを、きちんとbooleanとしてパースさせることが出来るようになりました。

fluentd について扱っている記事で、typesについて触れているものは見かけた記憶があまりありませんでした。 あんまりこの辺で引っかかることはないんでしょうか…?