joppot

コピペで絶対動く。説明を妥協しない

サーバ プログラミング

fluentdでrails logをtailで直接取得する方法

投稿日:2014年8月27日 更新日:

Pocket

09ujhnf

概要

追記) この記事はだいぶ古くなってしまったので、新しく書き直しました。
こちらの方を参照した方が多分良いことが書いてあります。
https://joppot.info/2017/03/17/3521

みなさんこんにちはcandleです。今回はrailsのrails logをfluentdから取得する方法を行ってみたいと思います。

fluentdはapacheのaccessログをとるフォーマットは予め作成されています。
しかし、railsのログとなると、自分で正規表現を用いたフォーマットを作る必要がでてくるわけです。

ただ、fluentdの正規表現は癖があり未だによく分かっておらず、難しいものです。

そこでruby on railsで開発をしている人ならgemを探すわけです。
act-fluent-loggerというのがその中でも一番railsログを取得する方法としては無難なのですが、問題がありました。

それはFatalの情報を取れない問題です。
そこで、今回は私の苦戦とともにrails logを取得する方法を紹介します。

前提

railsのテスト用のウェブサービスが1つある。

今回はもう既にwebrickかapacheまたはnginxでruby on railsが自由に動かせるのが前提になります。まだ出来てない人はscaffoldなどで簡単なウェブサービスを作っておいてください。

fluentdがインストールされている

ruby on railsを動かすマシーンにfluentdがインストールされている事が前提になります。
まだの人は下の記事を参考にしてください。

gemを使ってcentosにfluentdサーバを構築する

私が今回紹介する環境はvagrantのCentos6.5にapacheとpassengerでruby on railsを動かします。
もちろんwebrickの環境でも問題ありません。

SPONSORED LINK


railsのログフォーマットを変更する

railsのログのフォーマットはデフォルトで下のような感じになっていると思います。

defaultrailslog

まずはfomatterを有効にします。railsプロジェクトの中のconfigフォルダの中にdevelopment.rbとtest.rb、production.rbがあります。今動いているrailsの環境にあったファイルを開きます。私はproductionモードで動かしているのでproduction.rbを開きます。webrickを使っている普通のモードならdevelopment.rbを開いてください。

そしたら、下の2行を追加します。

config.logger = Logger.new(config.paths["log"].first)
config.logger.formatter = Logger::Formatter.new

editlogformat

この記述を書いたら、railsサーバを再起動しましょう。

bundle exec rails s

かpassengerの場合は

sudo service httpd restart

もう一度railsプロジェクトのlog/production.logかlog/development.logを見ると、下のようにログフォーマットが変更されています。

good format log

という感じになります。

一見これで、fluentdがrailsログを取得できそうですが、幾つか問題があります。

1つは先頭の「I,」という所、これはログレベルの頭文字を表しているのですが、その横に同じように「INFO」と書いてあります。同じ情報は2つもいらないので、この「I,」の部分は削除します。

2つ目は自分もよく知らないのですが、#が付いたプロセスIDです。fluentd上では#はコメントアウトを表しており、この記号は使えません(自分がしらないだけで実は使えるのかもしれない)。#は取り除いておきます。

3つ目はメッセージの部分の区切りがないことです。例えば「Completed 200 OK in 14ms (Views: 9.2ms | ActiveRecord: 1.9ms)」と「 Rendered memos/index.html.erb within layouts/application (7.7ms)」は先頭に空白があったりして、もしかすると正規表現を書いたさいに漏れる可能性があります。そこで明示的にシングルクォーテーションで囲みそこをメッセージとみなすことにします。もちろんこのやり方は私が試行錯誤した上での方法でもしかするとよりより方法があるかもしれません。

以上3つの問題を解決するためにruby のlogger formatの関数をオーバーライドして書き換えます。

railsプロジェクトのconfig/environment.rbを開きます。

oepnenvrinmentlrb

下のコードを記入しましょう。


class Logger
  class Formatter
    def call(severity, time, progname, msg)
      if msg.class.to_s == "String"
        msg = msg.gsub(/\n/, "")
        if msg.present? && !msg.include?("assets") && !msg.include?("erb")
          format = "[%s %d] %5s -- %s: \'%s\'\n"
          format % ["#{time.strftime('%Y-%m-%d %H:%M:%S')}.#{'%06d' % time.usec.to_s}",$$, severity, progname, msg2str(msg)]
        end
      end
    end
  end
end

loggercode

始めのif文でmsgがnilクラスでないか判定します。もしもnilの場合はその後のpresent?関数でエラーがでてしまうので、先にnilが来たら弾くようにします。msg.gsubで改行コードを削除します。なぜこれをやるかというと、Fatalエラーの様に複数行のログを吐き出す場合fluentdは1行毎ログと判断してしまうからです。本当はfatalエラーのメッセージにもかかわらず、改行が入ってしうまうと別のログとして判断されてしまいます。そこで\nを無くすことでそれを回避します。

backslushn

format =以下でfluentdからみて取りやすいフォーマットに変更しています。

保存しましょう。
もう一度、railsサーバを再起動してlog/development.logかlog/production.logを見ましょう。下のようになっていれば成功です。

perfectformat

fatalのところを見ても分かるように、\nが削除されて1行になっていますね。

これでrails logの設定は完了しました。

fluentdの準備

今回、rails logを取得するにあたり、予め用意するものがあります。それを先に準備しておきましょう。

fluent-plugin-rewriteをインストールする

fluent-plugin-rewriteをインストールします。下のコマンドでインストールしましょう。

gem install fluent-plugin-rewrite

installfluentrewrite

fluentdのログを保存するフォルダを作る

もしも、fluentdのログを保存する場所がまだ作成されていない場合は下のコマンドでfluentdのログを保存する場所を作成しておきましょう。

sudo mkdir /var/log/fluent/
sudo chown root:`whoami` /var/log/fluent/
sudo chmod 770 /var/log/fluent/

準備ができました。

rails logを取得する為のfluentdの設定

次にfluentdの設定を行います。fluentdにはrails logを取得するフォーマットがまだ用意されていないので独自に作る必要があります。

もしも、fluent.confが作成されてない場合は下のコマンドで作成しておきましょう。

sudo mkdir /etc/fluent/
sudo chown root:`whoami` /etc/fluent/
sudo chmod 775 /etc/fluent/
 
cd /etc/fluent/
fluentd --setup ./

fluent.confに下の内容を貼り付けましょう。

<source>
  type tail
  path railsログがあるフルパス #例)/var/www/rails/bootstrap3/log/production.log
  tag rails.log
  pos_file /var/log/fluent/rails.pos
  format /\[(?<date>\d{1,4}-\d{1,2}-\d{1,2} \d{1,2}:\d{1,2}:\d{1,2}.\d{1,6}) (?<process_id>[^ ]*)\] *(?<log_level>[^ ]*) -- : '(?<message>[^\']*[^\]]*)'/
</source>

<match rails.log>
  type rewrite
  remove_prefix rails.log
  add_prefix filtered
  <rule>
    key     message
    pattern \n
    replace
  </rule>
  <rule>
    key     message
    pattern \"
    replace '
  </rule>
</match>

<match filtered>
  type file
  format json
  path /var/log/fluent/rails_log
  time_slice_format %Y%m%d
  time_slice_wait 1s
  compress gzip
</match>

pathでrailsプロジェクトのlogフォルダにあるproduction.logないしdevelopment.logを参照します。参照先のパスは各自のものにしてください。

肝心のformatですが、これは先ほど変更したrails logのフォーマットに合わせています。
railsのログをrails.logというタグを付けてrewriteになげます。

type rewriteでは\nが万が一ある場合は削除して、\”はシングルクォーテーションに変更します。
rewriteしたものをfilteredというタグにして、type fileに送ります。

fype fileでは /var/log/fluent/にrails_logというファイルを生成してそこにログを保存します。
ファイルの分割は1日単位で行っています。

以上がfluentdがrails logを取得する為の設定です。


fluentdとrailsを動かしてログを取得する

では実際にrailsとfluentdを動かしてrails logが取得できるか試してみましょう。

まずはrailsを動かします。
webrickの場合は

bundle exec rails s

apacheのpassengerの場合は

sudo service httpd restart

次にfluentdを起動します。本番環境では恐らくfluentdが自動起動に成っていると思いますが、今回はfluentdを手動で起動します。

fluentd -c /etc/fluent/fluent.conf

そしたら、サーバにアクセスしてみましょう。

accessmyrailsservice

railsのログがfluentdで取得出来ているか確認します。

cd /var/log/fluent/

に移動して、rails_log.20982みたいなのがあるか確認します。
ありますね。

okwave

中身をみると、取得できています。

Ihadrailslog

まとめ

fluentdはまだrailsのログを取るフォーマットを公式には出していませんが、apacheのerror_logのフォーマットを公式が出したようにその内、でるかもしれませんそれまではこれを使えると便利でしょう。

スポンサードリンク

「為になったなぁ」と思ったら、シェアお願いします。

-サーバ, プログラミング
-,

執筆者:


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

cakephp2.5.6をfabric+cuisineを使用してインストールする

概要 みなさんこんにちはcandleです。今回はcakephp2.5.6の環境構築をfabricを使用して、インストールしてみましょう。cakephpはrailsと比べると100倍くらい簡単に環境構築 …

fabricでmysqlコマンドを実行する関数を自作する

概要 皆さんこんにちはcandleです。今回はfabricからリモート先のサーバのmysqlを実行するための環境変数と関数を作成したいと思います。 mysqlは一般にmysqlコマンドをログインしてか …

macにmemcachedをインストールする方法と動作確認

概要 memcachedはrailsやphpのセッションを保持しておく時に使うソフトというかサーバ的なものです。一般にSNSやログイン式のサービスを提供する時はセッションというのを持ちます。セッション …

vagrantで取得したlet’s encryptのssl証明書をec2のnginxで使用する

概要 みなさんこんにちはcandleです。今回は取得したvagrantのubuntuで取得したlet’s encryptを実際に使用してみます。 もしも、まだ取得してない人は前回の記事を確 …

phpmyadminでmysqlデータベースの照合順序を変更する

概要 みなさんこんにちはcandleです。 ちょっとした事なのですが、意外に分からなかったのでまとめました。 phpmyadminを使ってデータベースを作ると、うっかり、utf8_general_ci …

  • English
  • 日本語

プロフィール


ベンチャー企業のCTOをやってます。大学時代にプログラミングを始め、javaから入門し、C++へて、PHPへと進み、会社ではRailsを使用。自動化が大好きなプログラマー

スポンサードリンク

アーカイブ