Help us understand the problem. What is going on with this article?

Fluentd 経由で BigQuery に Schema-less なログを入れる

More than 3 years have passed since last update.

背景

gumi で提供しているソーシャルゲームは, サーバ/クライアント共に様々なログを Fluentd 経由で各種データストアに入れており, 適宜, 解析を行っている.

ログの種別により, Schema-full or Schema-less を選択しているが, 本記事では Schema-less なログの取り扱いを話題とする.

Schema-less なログの必要性

サーバ/クライアントの開発時から運用時まで, 常に次のような要望がある.

「気軽に適当なフォーマットでログを出力したい」

Schema-full なデータストアを採用する場合, 開発者に次のルールを強いる必要がある.

  • ログ出力前にテーブルのスキーマを定義せよ
  • ログ出力中にテーブルのスキーマを変更するなら, 別テーブルにせよ

これらのルールを開発者が守らない場合, Fluentd 側でエラーが発生するため, 開発者はインフラ担当のヘイトを稼ぐことになる. そして, インフラ担当に怒られた開発者は, 別の手段を模索し始め, 各プロジェクトごとに別々の仕組みが構築される.

よって, Schema-less なデータストアを使用し, Schema-less なログを出力する必要がある.

データストアの選定

Schema-less なデータストアを選定する場合, 筆者は, まず始めに MongoDBElasticsearch を候補にあげる. その後, Schema-full だが, データ取得時にフィールドに格納されている JSON フォーマット文字列から必要な情報を部分的に抜き取れる RedshiftBigQuery を連想する.

それぞれのデータストアに得手不得手があるため, gumi では, 適宜, 用途により使い分けている(一つのログを複数の用途で使用するため, ログの複製を複数のデータストアに保存することが多い).

今回の要件は, 「気軽に適当なフォーマットのログを出力したい」 であるため, 次の観点から BigQuery を採用した.

  • SQL なら書ける人が多い
  • ディスクスペースを考慮する必要がない
  • JSON 関連の関数の応答速度が速い
  • ModeAnalytics などで楽にグラフを作成できる

蛇足だが, 前述した他のデータストアを, gumi では次の用途で使用している.

  • MongoDB - 行動ログを入れ, カスタマーサポート時に使用
  • ElasticSearch - 自由入力文字列を入れ, 伏字処理や特定単語の検索に使用
  • Redshift - 検索頻度は高いが, 年単位で遡る事がない場合, BigQuery の代わりに使用
  • S3 & Glacier - 蛇足の蛇足. あらゆる全てのログのバックアップに使用

その他の前提条件

サーバ/クライアントから何らかの経路を辿り Fluentd へログが渡されていることを前提条件とする.

ログの取り扱い

ログを JSON フォーマット文字列にシリアライズする

前述した通り, BigQuery は Schema-full なデータストアであるため, ログを JSON フォーマット文字列に変換し, 一つのフィールドに入れる必要がある.

gumi では, ログを JSON フォーマット文字列にシリアライズする Fluentd Plugin fluent-plugin-record-serializer を作成し, 運用している.

Plugin をインストール後, Fleuntd に次のような設定を追加し,

fluent.conf
<filter pattern>
  type record_serializer
</filter>

次の様なログを送ると,

{
  "spam": "ham",
  "egg": "cheese"
}

次の様にシリアライズされる.

{
  "tag": "pattern",
  "payload": "{\"spam\": \"ham\", \"egg\": \"cheese\"}"
}

ちなみに, fluent-plugin-record-serializer は Oj をインストールすると CPU 負荷が減る.

BigQuery への保存

Fleuntd から BigQuery にログを入れるため, fluent-plugin-bigquery を使用する.

次の様な本末転倒な Schema ファイルを設置し,

schemaless_schema.json
[
  {
    "name": "tag",
    "type": "STRING"
  },
  {
    "name": "time",
    "type": "INTEGER"
  },
  {
    "name": "payload",
    "type": "STRING"
  }
]

Fleuntd に次のような設定を追加すると,

fluent.conf
<match pattern>
  type bigquery

  method insert
  auto_create_table true
  schema_path /path/to/schemaless_schema.json

  # ..snip..  
</match>

指定したプロジェクトのテーブルに, Schema-less なログが入る.

ログの確認

JSON_EXTRACT 関数を使用し, 必要なログを取得する.

SELECT JSON_EXTRACT(payload, '$.spam') as spam
  FROM [pattern_20151204] 
 WHERE JSON_EXTRACT(payload, '$.egg') = 'cheese' 

まとめ

SELECT や WHERE 句に payload を指定すると, 非常にサイズの大きいフィールドを扱うため, BigQuery 破産の可能性が上昇する. ご利用は計画的に.

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした