Railsとkibanaで新しい情報がまとまってなかったので、まとめました。
出来ること
- Rails logの可視化
- アプリの速度の分析、高速化などに使える
- デプロイ時に、各種数値変化をリアルタイムでモニタリングできる(切り戻しの判断)
- ステータスコードの割合
- 処理時間の分布
- デプロイ時に、各種数値変化をリアルタイムでモニタリングできる(切り戻しの判断)
- クローラーや、PC、スマフォなどのユーザーの動向を分析
- 特定のユーザーの行動を追うことが出来る(運用保守)
- アプリの速度の分析、高速化などに使える
お試しなのでいろいろ妥協している
kibana 4.4.1
elasticsearch 2.2
ネットワーク、セキュリティーグループの設定は省略。
前提条件として、kibanaとrailsのサーバーは同じネットワークにいて、
private ipでやり取りしていることにする。
##Rails 下準備
gem "lograge" #elastic_search用 log整形
gem "logstash-event" #elastic_serach用ログをカスタマイズ
gem "rack-user_agent" #requestから、os, browserのバージョンが分かる(ログに情報をだしたいために利用)
fluentdエージェントにログを直接送ればよかったけど、わからなかったのでログを出力して
fluentdにtailさせることにした。
別途通常のログとは分けて別のログに出力した。
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
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のバージョンがあがったら、コケるようにしておく。
(バージョンアップ時に、ここだけ古い状態が続くと、アプリの動作がおかしくなるため)
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して確認
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
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
[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
この設定しないと外のネットワークからの接続ができない
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
動作確認
./kibana-4.4.1-linux-x64/bin/kibana
バックグラウンド起動(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
[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
<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
- 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で見れるようになっているはず。
参考URL・メモ
logstash-logger使えばtailしなくても行けそうかもしれない
stacktraceの部分の参考Gist
Qiita:Logging of Rails in Lograge