はのちゃ爆発

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

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

となっています。こうすると、valuetrue 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 になる件" でした。 長すぎたので流石にやめました。