MyCSS

2010/03/16

Railsのログをsyslog-ngで集約する はてなブックマークに追加

Railsのログをsyslog-ngを使って一カ所にまとめる手順をメモしておきます。
使用前

ここにRailsのサーバーが3台あります。前段にはロードバランサーが立っています。ログはデフォルトの場所にバラバラに記録されるので、記録としては相当使いにくいものになります。
使用後

ログ集計用のログサーバーを別途立てます。Railsアプリはsyslog経由でログを記録するようにします。syslogにはsyslog-ngを使い、Railsアプリが出したログはudp経由でログサーバーに随時転送するようにします。
今回は例として、ポート番号を5140番とします。
ログサーバーはudp:5140を見張っていて、ログが流れてきたらファイルに書き出すという算段です。

導入
そもそもなんでsyslog-ngなのか?という点に関してですが、個人的には導入のしやすさでした。もちろんその他も多くの利点があると思います。

作業としては、syslog-ngのインストールと設定、RailsアプリをSyslogLogger経由でのロギングに変更するだけです。既に運用が始まったものでも、結構簡単に移行出来ると思います。

今時syslog-ngを導入するには、パッケージで一発インストールでしょうから、お決まりの呪文を唱えましょう。※Ubuntu Linux Server 9.10で試しています。
sudo apt-get install syslog-ng
当たり前だけど、Railsサーバー、ログサーバーとも両方行います。

次に、RailsアプリのロギングをRubyのLoggerから、SyslogLoggerへ切り替えます。といってもやる事は簡単で、gemでインストールして、ちょこっと設定を変えるだけです。
sudo gem install SyslogLogger

config/environment.rbに以下の記述を追記します。
Rails::Initializer.run do |config|
  # (中略)
  config.gem 'SyslogLogger', :lib => 'syslog_logger'
  # (中略)
end
今回の想定では本番環境のみsyslogでロギングしたいので、config/environments/production.rbに下記を追記します。最初の行に書いておいた方が良いでしょう。
require 'syslog_logger'
RAILS_DEFAULT_LOGGER = SyslogLogger.new "rails_app"
rails_appはRailsアプリのログである事を識別するためのラベル(プログラム名)です。これはsyslog-ngで使用します。(rails_appというのは例です。解りやすいものにする方が良いでしょう。)


syslog-ngの設定(Railsアプリ側)
syslog-ngの設定そのものは簡単です。Railsアプリのサーバーではログをudpでログサーバーに向けて流す設定を行います。
syslog-ngの設定ファイルは、Ubuntuの場合だと
/etc/syslog-ng/syslog-ng.conf
にありますので、コイツに追記してやる事にします。
destination dr_rails_app {
    udp("192.168.1.100" port(5140));
};

filter f_rails_app {
    program(rails_app);
};

log {
    source(s_all);
    filter(f_rails_app);
    destination(dr_rails_app);
};
ここでは便宜的に、ログサーバーのIPアドレスを192.168.1.100としています。
destinationとfilterを定義して、それをlogでまとめるという感じです。
destinationは、見ての通り192.168.1.100へudpの5140ポートで送ると記述します。
filterはRailsアプリ側で指定したラベル(プログラム名)を記述します。
logの中の、source(s_all)というのは、Ubuntuだと全てのメッセージソースという事でデフォルトで定義されているものです。(これは環境によって書き方が変わってくる部分だと思います。)syslogがうけたログで、rails_appというラベルの付いたものだけを抽出し、それをログサーバーに送るという記述になっています。


syslog-ngの設定(ログサーバー側)
次にログサーバー側の設定です。
source s_rails_app {
    udp(ip("0.0.0.0") port(5140));
};

destination df_rails_app {
    file("/var/log/rails/production.log");
};

filter f_rails_app {
    program(rails_app);
};

log {
    source(s_rails_app);
    filter(f_rails_app);
    destination(df_rails_app);
};
sourceは自分自身のudp:5140です。
destinationはログの書き出し場所をファイルパスで示しています。
filterはRailsアプリ側で指定したラベル(プログラム名)を記述します。
これらをまとめて、logの中に記述します。

セキュリティの絡みでもっとやるべき事があるとは思いますが、基本的な事はこれだけです。
ログの取りこぼしが絶対あってはならないものであれば、udp経由での通信は厳しいので避けるべきです。

参考にさせていただいたサイト:

0 件のコメント :

コメントを投稿