LoginSignup
26
25

More than 5 years have passed since last update.

kibana4によるRailsアプリの可視化 EC2 Amazon Linux

Last updated at Posted at 2016-03-27

Railsとkibanaで新しい情報がまとまってなかったので、まとめました。

出来ること

  • Rails logの可視化
    • アプリの速度の分析、高速化などに使える
      • デプロイ時に、各種数値変化をリアルタイムでモニタリングできる(切り戻しの判断)
        • ステータスコードの割合
        • 処理時間の分布
    • クローラーや、PC、スマフォなどのユーザーの動向を分析
    • 特定のユーザーの行動を追うことが出来る(運用保守)

image

image

お試しなのでいろいろ妥協している

kibana 4.4.1
elasticsearch 2.2
ネットワーク、セキュリティーグループの設定は省略。
前提条件として、kibanaとrailsのサーバーは同じネットワークにいて、
private ipでやり取りしていることにする。

Rails 下準備

Gemfile
gem "lograge"        #elastic_search用 log整形
gem "logstash-event" #elastic_serach用ログをカスタマイズ
gem "rack-user_agent" #requestから、os, browserのバージョンが分かる(ログに情報をだしたいために利用)

fluentdエージェントにログを直接送ればよかったけど、わからなかったのでログを出力して
fluentdにtailさせることにした。
別途通常のログとは分けて別のログに出力した。

config/application.rb
unless Rails.env.test? #テストの時以外を想定
  #fluentdがtailする用のログを設定
  path                                   = "#{Rails.root}/log/lograge_#{Rails.env}.log"
  #100Mごとに捨てる(ローテート設定)
  config.lograge.logger                  = ActiveSupport::Logger.new(path, 1, 100.megabytes)
  config.lograge.enabled                 = true
  config.lograge.keep_original_rails_log = true
  config.lograge.formatter               = Lograge::Formatters::Logstash.new

  config.lograge.custom_options = lambda do |event|
    opts = { host:            event.payload[:host],
             user_id:         event.payload[:user_id],
             remote_ip:       event.payload[:remote_ip],
             user_agent:      event.payload[:user_agent],
             os:              event.payload[:os],
             os_version:      event.payload[:os_version],
             browser:         event.payload[:browser],
             browser_version: event.payload[:browser_version],
             es:              event.payload[:elasticsearch_runtime],
             category:        event.payload[:category_name], #アプリの出したい情報など
             time:            event.time }

    #error時のバックトレースなんかも見れたら保守が便利なので出す
    if stacktrace = event.payload[:stacktrace] 
      opts[:stacktrace]    = stacktrace
      opts[:error]         = event.payload[:error]
      opts[:error_message] = event.payload[:error_message]
    end
    opts
  end
end

app/controller/application_controller.rb
protect_from_forgery #←この記述はもともとあるはず、アプリの要件に合わせてオプションを記述、この記述がないとログが出力されない(csrf関連のrailsの設定)

def append_info_to_payload(payload)
  super
  payload[:host]                = request.host
  payload[:user_id]             = current_user.try(:id).to_s
  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[:category_name]       = params.try(:[], :category_name) #アプリの出したい情報
end

stacktraceを出力するためにモンキーパッチ
rails 4.2.5の時のパッチなので、別のバージョンの時は要確認
actionpack-4.2.5/lib/action_controller/metal/instrumentation.rb
response.statusを代入している所の例外処理の所を修正して、情報を追加している。

また、devlpment環境で、Railsのバージョンがあがったら、コケるようにしておく。
(バージョンアップ時に、ここだけ古い状態が続くと、アプリの動作がおかしくなるため)

config/initializer/kibana_log_stacktrace_patch.rb
module ActionController
  module Instrumentation
    def process_action(*args)
      if Rails.env.development? && Rails.version != "4.2.5"
        raise "#20年後の僕へ、4.2.5の時のgemの内容をコピーして持ってきています.バージョンがあがったら確認して, 変更があればコピーして下さい。actionpack-4.2.5/lib/action_controller/metal/instrumentation.rb"
      end
      raw_payload = {
        controller: self.class.name,
        action: self.action_name,
        params: request.filtered_parameters,
        format: request.format.try(:ref),
        method: request.request_method,
        path: (request.fullpath rescue "unknown")
      }

      ActiveSupport::Notifications.instrument("start_processing.action_controller", raw_payload.dup)

      ActiveSupport::Notifications.instrument("process_action.action_controller", raw_payload) do |payload|
        begin
          result = super
          payload[:status] = response.status
          result
        rescue => e
          #kibanaでstack_traceを見るために拡張している、他はそのまま
          payload[:error]         = e.class.name
          payload[:error_message] = e.message
          payload[:stacktrace]    = e.backtrace.join("\n\t")
          raise
        ensure
          append_info_to_payload(payload)
        end
      end
    end
  end
end

rails アプリを動かせばログが出力されるはず。
jqを使ってtailして確認

console
tail -f log/lograge_development.log | jq "."

AWS 下準備(elasticsearch kibanaのEC2)

インスタンス作成 amazone linux
仮想化されたストレージ(AmazonのElastic Block Storageなど)に注意:仮想化されたストレージはElasticsearchで十分に動作します。また、十分早く簡単に用意できることから魅力的です。しかし、残念なことに、ローカルストレージと比較すると本質的に遅いです。

よって、rootのストレージを拡張する。
とりあえず適当にrootのストレージを20GBにしてすすめた。

$ sudo yum update -y

日本時間に設定

$ sudo vim /etc/sysconfig/clock
/etc/sysconfig/clock
ZONE="Asia/Tokyo"
$ sudo ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
$ sudo reboot

elasticsearch2.2 インストール

sudo yum -y install java-1.8.0-openjdk-devel.x86_64
sudo rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch
sudo vim /etc/yum.repos.d/elasticsearch.repo
/etc/yum.repos.d/elasticsearch.repo
[elasticsearch-2.x]
name=Elasticsearch repository for 2.x packages
baseurl=http://packages.elastic.co/elasticsearch/2.x/centos
gpgcheck=1
gpgkey=http://packages.elastic.co/GPG-KEY-elasticsearch
enabled=1
sudo yum install elasticsearch -y
sudo vim /etc/elasticsearch/elasticsearch.yml

この設定しないと外のネットワークからの接続ができない

elasticsearch.yml
cluster.name: kibana_cluster #適当に名前つけとく
network.host: xxxx.xxxx.xxx.xxx #elasticsearchサーバーのip
http.port: 9200

起動

sudo /etc/init.d/elasticsearch start

確認

curl localhost:9200

pluginのinstall(好み)

sudo /usr/share/elasticsearch/bin/plugin install analysis-kuromoji
sudo /usr/share/elasticsearch/bin/plugin install mobz/elasticsearch-head
sudo /usr/share/elasticsearch/bin/plugin install royrusso/elasticsearch-HQ
sudo /etc/init.d/elasticsearch restart

kibana4.4.1 install

curl -L -O https://download.elastic.co/kibana/kibana/kibana-4.4.1-linux-x64.tar.gz
tar xzvf kibana-4.4.1-linux-x64.tar.gz
vim kibana-4.4.1-linux-x64/config/kibana.yml

image

動作確認

./kibana-4.4.1-linux-x64/bin/kibana

image

バックグラウンド起動(Nginx噛ませてやるのがめんどくさかったのでとりあえず妥協)

sudo ./kibana-4.4.1-linux-x64/bin/kibana  > ./kibana.log &

kibanaの動作確認
http://xxxx.xxxx.xxxx.xxxx:5601/

Railsが動いているEC2のfluentdの準備

fluentd install

sudo vi /etc/yum.repos.d/treasuredata.repo
/etc/yum.repos.d/tresuredata.repo
[treasuredata]
name=TreasureData
baseurl=http://packages.treasure-data.com/redhat/$basearch
gpgcheck=0
sudo yum install td-agent -y
sudo chkconfig td-agent on
sudo /usr/lib64/fluent/ruby/bin/fluent-gem install --no-ri --no-rdoc fluent-plugin-elasticsearch
sudo vim /etc/td-agent/td-agent.conf
td-agent.conf
<source>
  type     tail
  format   json
  tag      rails
  path     /path/to/log/lograge_production.log
  pos_file /path/to/log/lograge_production.log.pos
  time_key time
</source>

<match rails>
  type elasticsearch
  retry_limit 5
  host xxxx.xxxx.xxxx.xxxx #elasticsearch ip
  port 9200
  logstash_format true
  logstash_prefix lograge
  flush_interval  1s
</match>

権限周りで起動しても落ちるため、fluentdをroot権限で実行するよう変更

sudo vim /etc/init.d/td-agent
/etc/init.d/td-agent
- DAEMON_ARGS=${DAEMON_ARGS---user td-agent}
+ DAEMON_ARGS=${DAEMON_ARGS---user root}
TD_AGENT_ARGS="${TD_AGENT_ARGS-/usr/sbin/td-agent --user root --group td-agent --log /var/log/td-agent/td-agent.log}"

起動

sudo /etc/init.d/td-agent start
# 必ずstatusで起動状態を確認する
sudo /etc/init.d/td-agent status

status確認でコケたらログをみてみる

less /var/log/td-agent/td-agent.log

ここまでできたら、Railsが動けばelasticsearchにログが貯まり、
kibanaで見れるようになっているはず。

image

参考URL・メモ

logstash-logger使えばtailしなくても行けそうかもしれない
stacktraceの部分の参考Gist
Qiita:Logging of Rails in Lograge

26
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
25