RailsのログをfluentdでBigQuery、あるいはS3に取り込む

GCP BigQueryやAWS Athenaを実際に触る機会が欲しかったので、RailsのログをfluentdでBigQueryやS3に取り込んでみます。 とりあえず触ることが目的で、実用できるかはとりあえず脇においておきます。

なお、fluentd(td-agent)はOS Xに0.14.21 をインストールしています。

Rails fluent logger

Railsのログはデフォルトでは log ディレクトリに出力されるため、これをfluentdで扱えるようにする必要があります。

ドキュメント Collecting and Analyzing Ruby on Rails Logs | Fluentd に従って、logrageact-fluent-logger-rails を使ってみます。

ほぼドキュメント通りですが、以下のように設定しました。

config/application.rb

  class Application < Rails::Application
    config.log_level = :info
    config.logger = ActFluentLoggerRails::Logger.new
    config.lograge.enabled = true
    config.lograge.formatter = Lograge::Formatters::Json.new
    config.lograge.custom_options = lambda do |event|
      exceptions = %w(controller action format id)
      {
        params: event.payload[:params].except(*exceptions)
      }
    end
  end

custom_optionsでリクエストパラメタをログに出力するようにしています。

config/fluent-logger.yml

development:
  fluent_host:   '127.0.0.1'
  fluent_port:   24224
  tag:           'foo'
  messages_type: 'string'

アプリケーションの設定はこれで終わりです。

fluentd + BigQuery

次は、BigQueryにログを出力です。 fluent-plugin-bigquery を使います。

/etc/td-agent/td-agent.conf

<match foo>
  @type parser
  key_name messages
  format json
  tag rails
</match>

<filter rails>
  @type record_transformer
  remove_keys location 
</filter>

<match rails>
  @type copy
  <store>
    @type stdout
  </store>
  <store>
    @type bigquery
    method insert
    auth_method json_key
    json_key /path/to/json_key

    auto_create_table true

    project your-project-id
    dataset rails_playground
    table   logs
    schema [
      {"name": "method", "type": "STRING"},
      {"name": "path", "type": "STRING"},
      {"name": "format", "type": "STRING"},
      {"name": "controller", "type": "STRING"},
      {"name": "action", "type": "STRING"},
      {"name": "status", "type": "INTEGER"},
      {"name": "duration", "type": "FLOAT"},
      {"name": "view", "type": "FLOAT"},
      {"name": "db", "type": "FLOAT"},
      {"name": "params", "type": "STRING"}
    ]
  </store>
</match>

BigQueryのスキーマも設定します。

f:id:kotaroito2002:20170922090630p:plain

実際にクエリを実行してみた結果がこちら。

f:id:kotaroito2002:20170922091321p:plain

fluentd + S3

次はfluentdでS3にログを保存してみます。 まずはtd-agentの設定です。Amazon S3 Output Plugin | Fluentdに従えばOKです。

<match pattern>
  @type s3

  aws_key_id YOUR_AWS_KEY_ID
  aws_sec_key YOUR_AWS_SECRET_KEY
  s3_bucket YOUR_S3_BUCKET_NAME
  s3_region ap-northeast-1


  path kotaroito/rails-playground/dt=%Y-%m-%d/
  s3_object_key_format %{path}%{time_slice}_%{hostname}_%{index}.%{file_extension}

  <buffer tag,time>
    @type file
    path /var/log/td-agent/s3
    timekey 60
    timekey_wait 1m
    timekey_use_utc true # use utc
  </buffer>

  format json
  include_time_key true
</match>

検証を早くしたいので、timekey は60に設定しています。 これでログがS3に保存されていきます。

{"method":"GET","path":"/books","format":"html","controller":"BooksController","action":"index","status":200,"duration":184.47,"view":156.19,"db":1.52,"params":{},"time":"2017-09-27T14:00:11Z"}
{"method":"GET","path":"/books/6","format":"html","controller":"BooksController","action":"show","status":200,"duration":43.6,"view":37.93,"db":0.34,"params":{},"time":"2017-09-27T14:00:21Z"}

Athena

S3に保存しただけじゃ面白くないので、以前から気になっていたAthenaを使ってみることにします。

Amazon Athena (サーバーレスのインタラクティブなクエリサービス) | AWS

Amazon Athena はインタラクティブなクエリサービスで、Amazon S3 内のデータを標準的な SQL を使用して簡単に分析できます。Athena はサーバーレスなので、インフラストラクチャの管理は不要です。実行したクエリに対してのみ料金が発生します。

Athena は簡単に使えます。Amazon S3 にあるデータを指定して、スキーマを定義し、標準的な SQL を使ってデータのクエリを開始するだけです。多くの場合、数秒で結果が出てきます。Athena を使用すると、分析用データを準備するための複雑な ETL ジョブは不要になります。これによって、誰でも SQL のスキルを使って、大型データセットをすばやく、簡単に分析できるようになります。

Athenaには Getting Started — User Guideにてチュートリアルが用意されているので、これを最初にやると雰囲気が掴めます。

やるべきことは、CREATE TABLE をして、

CREATE EXTERNAL TABLE IF NOT EXISTS default.rails_logs (
  `method` string,
  `path` string,
  `format` string,
  `controller` string,
  `action` string,
  `status` int,
  `duration` float,
  `view` float,
  `db` float,
  `params` map<string,string>,
  `time` string 
)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
WITH SERDEPROPERTIES (
  'serialization.format' = '1'
) LOCATION 's3://your-bucket-name/path_to_log_dir/'
TBLPROPERTIES ('has_encrypted_data'='false')

あとはクエリを実行するだけです。

SELECT * FROM default."rails_logs" limit 10

f:id:kotaroito2002:20170929085434p:plain

ね、簡単でしょ?

と言いたいところなんですが、色々調べると「S3にログだけ置いておけばあとはAthenaがいい感じやってくれるぜー」という夢のような話はなく、(まともに運用するなら)パーティショニング、ログフォーマット、実行結果の保存等、考えることは多そうです。

qiita.com

日常的に見ることはないログをS3に保存しておき、ad-hocに分析したいという時にはAthenaは1つの選択肢かもなと思いました。 (その他ユースケースでAthenaが最適解になるかはもうちょっと自身が勉強しないと、答が出なそう)

まとめというか、感想

logrageとact-fluent-logger-railsを使うと、RailsのログをかんたんにBigQueryやS3に取り込みできました。 ただし、logrageは例外ログまではサポートしていない(FAQ)ので、例外トラッキングサービス(airbrake.ioなど)別の方法を用意する必要がありそうです。

Athenaはどんなユースケースに使えるかもう少し研究したいところ。