fluentd で LTSV なログを BigQuery に送るときの注意点 (追記あり)
※ 2016/08/01 追記 対策をとある方から教えて頂いたので、後日別記事にまとめます。 ※
サーバのログなんかをLTSV形式で吐き出して、それをfluentd経由でBigQueryに蓄積していく。いいと思います。
とても良いのですが、ちょっとハマったところがあったのでメモ書き。
現象
タイトル通り、LTSV形式で吐き出されたログファイルをfluentdでBigQueryに送ります。
このとき、fluentdからBigQueryにデータを送るためのプラグインとして、fluent-plugin-bigquery
を使います。
GitHub - kaizenplatform/fluent-plugin-bigquery
これを使うと、手軽にfluentdからBigQueryにデータを送ることができます。
※ 送り方は割愛します。以下のページが参考になります。
fluent-plugin-bigqueryを使ってログをbigqueryに流してみる - tjinjin's blog
しかし、困ったことが一つ。
スキーマファイルを用意し、その中で"type": "boolean"
を指定していても、
実際のログデータをBigQueryに送ると、そのboolean
と指定されているデータの中身にかかわらず、
全てtrue
としてBigQueryに格納されてしまいます。
原因
たぶんこれっぽい、という程度のものですが。
fluent-plugin-bigquery
中に、以下の様なコードがあります。
fluent-plugin-bigquery/schema.rb at master · kaizenplatform/fluent-plugin-bigquery · GitHub
Schemaに記されたデータ型に応じて、ソースの内容を適切な形式に変換する処理を行う部分、だと思います。
上記のリンクは、本記事に関係のあるBooleanFieldSchema
にアンカーを貼っています。
上記のBooleanFieldSchema
は、その名前の通り、boolean
型を扱うためのクラスです。
その中にformat_one
というメソッドがあり、これでソースから取り込んだデータをboolean
にしているものと思われます。
どうやって変換しているのか見てみると、
!!value
となっています。こうすると、value
をtrue
or false
に変換できます。
変換規則は以下のページがわかりやすいです。
bool値に変換する「!!」 - 成らぬは人の為さぬなりけり
この方法で値を boolean
に変換するとき、特に文字列は以下のようになります。
> !!'true' # => true > !!'false' # => true > !!'' # => true
あらゆる文字列が true
と判定されてしまうのです。
文字列が true
であること自体はいいのですが、問題はその文字列が false
だったときです。
(false
という文字列を true
と判定すべきか false
と判定すべきか、どちらがいいかはケースバイケースだと思いますが…)
今回のようにLTSVをソースとして読み取ったデータは、恐らく全て文字列として取り込まれます。
他の数値データなどは正しく型変換(?)が行われるようですが、boolean
は上記の性質から、
LTSV -> fluentd(fluent-plugin-bigquery) -> BigQuery
とすると、BigQueryにデータが格納された時点で boolean
型のカラムのデータが全てtrueになってしまいます。
元のデータがtrue
でもfalse
でも空文字列でも、です。
対処法
対応策がちゃんとありました。後日改めてまとめます。
正直どうにも対処のしようがありません…
仕方がないので、ひとまず false
の場合はLTSVに対応するデータを与えず、BigQueryに null
が入るようにしています。
BigQueryにデフォルト値を設定できるのであれば、デフォルトを false
にすればそれっぽくなるかもしれません。
余談
元々のタイトルは "fluentd で LTSV なログを BigQuery に送ると boolean が全部 true になる件" でした。 長すぎたので流石にやめました。