EBに置いたrailsからAmazon Kinesis Data FirehoseでlogをamazonESに投げる

はじめに

ちょっとググるとamazonESにログを送信するのにfluentd(td-agent)を利用するケースが多いですが、その場合以下のライブラリを利用するみたいなのが多く出てきます。
https://github.com/atomita/fluent-plugin-aws-elasticsearch-service
ただ、メンテナンスされてないっぽいのと、Amazon Kinesis Data Firehoseを利用したほうが楽そうだったので設定してみました。

※EBの設定はしてあるものとします

Railsの設定

logrageでjsonのlog吐き出す

参考
https://qiita.com/ichi_s/items/7cf6ce5dbfaa00976dd4

Gemfile
gem 'lograge'
gem 'logstash-event'
gem "rack-user_agent"

config/initializers/lograge.rb
Rails.application.configure do
  config.lograge.enabled = true
  config.lograge.base_controller_class = ['ActionController::API', 'ActionController::Base']
  config.lograge.formatter = Lograge::Formatters::Logstash.new
  config.lograge.keep_original_rails_log = true
  config.lograge.logger = ActiveSupport::Logger.new "#{Rails.root}/log/lograge_#{Rails.env}.log"
  config.lograge.custom_options = lambda do |event|
    payload = event.payload

    data = payload.slice(*%i(
      uuid host remote_ip user_agent os os_version browser browser_version user_id 
    ))

    if payload[:exception]
      e = payload[:exception_object]
      data[:exception_class] = e.class.to_s
      data[:exception_message] = e.message
      data[:stacktrace] = "#{e.class}: #{e.message}\n" + (e.backtrace || []).join("\n")
    end

    data
  end
end

application_controller.rb
  def append_info_to_payload(payload)
    super
  
    payload[:uuid]                = request.uuid
    payload[:host]                = request.host
    payload[:remote_ip]           = request.remote_ip
    payload[:user_agent]          = request.user_agent
    payload[:os]                  = request.os
    payload[:os_version]          = request.os_version
    payload[:browser]             = request.browser
    payload[:browser_version]     = request.browser_version
    payload[:user_id]             = current_user.id.to_s if current_user.present?
  end

AmazonES設定

この辺を参考に画面からポチポチ作成していきます。
https://docs.aws.amazon.com/ja_jp/elasticsearch-service/latest/developerguide/es-createupdatedomains.html

access policy参考
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::IAMユーザーのARN",
        ]
      },
      "Action": "es:*",
      "Resource": "arn:aws:es:ESのARN"
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "es:*",
      "Resource": "ESのARN",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": "許可したいIPアドレス"
        }
      }
    }
  ]
}

Amazon Kinesis Data Firehose設定

この辺を参考に画面からポチポチ設定していきます
https://docs.aws.amazon.com/ja_jp/firehose/latest/dev/what-is-this-service.html

.ebextensionsの下に設定ファイルを置きます。今回はnginx、railsのログをFirehoseに送信します
.ebextensions/0-aws-kinesis-agent.config
packages: 
  yum:
    aws-kinesis-agent: []
files:
  "/etc/aws-kinesis/agent.json":
    owner: root
    group: root
    content: |
      {
        "cloudwatch.emitMetrics": true,
        "cloudwatch.endpoint": "https://monitoring.ap-northeast-1.amazonaws.com",
        "firehose.endpoint": "https://firehose.ap-northeast-1.amazonaws.com",
      
        "flows": [
          {
            "filePattern": "/var/app/current/log/lograge_production.log*",
            "deliveryStream": "設定したdeliveryStream名"
          },
          {
            "filePattern": "/var/log/nginx/access.log*",
            "deliveryStream": "設定したdeliveryStream名",
            "dataProcessingOptions": [
              {
                "optionName": "LOGTOJSON",
                "logFormat": "COMMONAPACHELOG"
              }
            ]
          }
        ]
      }

.ebextensions/1-aws-kinesis-agent.config
commands:
  01-command:
   command: service aws-kinesis-agent restart

これで完了なのでdeployします

ログのローテート時にエラーになる対処

一件うまくいったように見えますが、ログのローテート時に以下のエラーが永遠に出続けます
2018-04-03 17:51:21.779+0000 ip-10-199-93-156 (FileTailer[fh:lukew_nginx_access_log:/var/log/nginx/access.log]) com.amazon.kinesis.streaming.agent.tailing.FileTailer [ERROR] FileTailer[fh:lukew_nginx_access_log:/var/log/nginx/access.log]: Error when processing current input file or when tracking its status.
java.lang.IllegalArgumentException: Current file is not contained in current snapshot!
 at com.google.common.base.Preconditions.checkArgument(Preconditions.java:122)
 at com.amazon.kinesis.streaming.agent.tailing.TrackedFileRotationAnalyzer.(Unknown Source)
 at com.amazon.kinesis.streaming.agent.tailing.SourceFileTracker.updateCurrentFile(Unknown Source)
 at com.amazon.kinesis.streaming.agent.tailing.SourceFileTracker.refresh(Unknown Source)
 at com.amazon.kinesis.streaming.agent.tailing.FileTailer.updateRecordParser(Unknown Source)
 at com.amazon.kinesis.streaming.agent.tailing.FileTailer.processRecords(Unknown Source)
 at com.amazon.kinesis.streaming.agent.tailing.FileTailer.runOnce(Unknown Source)
 at com.amazon.kinesis.streaming.agent.tailing.FileTailer.run(Unknown Source)
 at com.google.common.util.concurrent.AbstractExecutionThreadService$1$2.run(AbstractExecutionThreadService.java:60)
 at com.google.common.util.concurrent.Callables$3.run(Callables.java:95)
 at java.lang.Thread.run(Thread.java:748)
issueにも上がってます
https://github.com/awslabs/amazon-kinesis-agent/issues/50

対処法としては、EBの場合にローテートされたファイルは同じディレクトリではなくて、ディレクトリの下に出来るのでダミーファイルをおいてあげることで解決しました。


/var/log/nginx/access.log.dummy
/var/app/current/log/lograge_production.log.dummy

1-aws-kinesis-agent.configに以下を追加
commands:
  01-command:
    command: touch /var/log/nginx/access.log.dummy
rails側のログは空ファイルのログをコミットします
log/lograge_production.log.dummy

これでいいのかわかりませんが、今のところ問題なさそう

コメント

このブログの人気の投稿

メッセージUIライブラリMessageKitの紹介

YPImagePickerで加工動画が変換できない

AWS DEV DAY 2018に行ってきました