joppot

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

サーバ プログラミング

railsのfluent-loggerとdevise gemを使ってユーザーの行動をfluentdサーバに収集する

投稿日:

Pocket

i9idf

概要

fluentdと言えば、ビックデータで扱うようなデータを集め出力するサーバですが、これとrailsのfluent-logger gemとdevise gemを組み合わせてユーザーの行動ログをとってみたいと思います。

前提

ローカルかLAN内かVMでfluentdが1台自由に動かせる

deviseを使用した適当なrailsアプリケーションがある

SPONSORED LINK


fluent-logger gemをインストールする

適当なrailsアプリケーションのGemfileを開きます。私は例によって、bootstrap3というプロジェクトを使います。

Gemfileを開いたら、下の内容を書き込みます。

gem 'fluent-logger'

writefuentlogger2

保存したら、下のコマンドでfluent-loggerをインストールします。

bundle install

お約束ですね。
これでfluent-loggerがインストールできました。


ユーザーの行動ログを取るプログラムを書く

railsプロジェクトのapp/controllers/application_controller.rbを開きます。

openapp2

開いたら、class ApplicationControllerの中に下の記述を書き込みます。

Fluent::Logger::FluentLogger.open(nil, :host=>'localhost', :port=>24224)
before_action :fluentpost
def fluentpost
  if user_signed_in?
    Fluent::Logger.post("debug.ruby",{"id"=>current_user.id,"user_name"=>current_user.email,"url"=>request.fullpath,"time"=>Time.now.to_s(:db)})
  else
    Fluent::Logger.post("debug.ruby",{"id"=>"guest_id","user_name"=>"guest","url"=>request.fullpath,"time"=>Time.now.to_s(:db)})  
  end
end

loggerprogram-1

railsの設定はこれだけです。

解説していきます。
自明の理かもしれませんが、ApplicationControllerは他の全てのコントローラーのスーパークラスですね。自分で作ったコントローラーは全てこのApplicationControllerを継承しています。ここにfluentdにログを投げる設定をすれば、他の全てのコントローラーでfluentdにログを投げるプログラムが実行されるわけです。

今記述したソースコードは始めにfluentdサーバにアクセスする設定を書いています。

host=>ではlocalhostを指定しています。もしも別のサーバでfluentdが動いている場合はそのホスト名かIPアドレスを入れてあげましょう。port=>ではfluentdのデフォルトポート24224を設定します。

次に、before_actionでfluentpost関数を実行させます。こうすることで、全てのコントローラーはアクションが実行されるまえにこのfluentpost関数を実行します。この書き方は多少問題を抱えています。ビューが無いアクションも実行されてしまいます。でも致命的な問題ではないので嫌な人はfilterを使うなりして対処してください。

最後のfluentpost関数の記述はまずif文でログインしているユーザかログインしていないユーザーか判断します。タグuser.accessを付けて、ログインしていないユーザーはidとemailの値をguestにして、ログインしているユーザーはdeviseのidとemailをいれて、urlと日にちをfluentdに投げています。

さらにカスタマイズすることも可能ですが、カスタマイズする際に気をつけて欲しいのは値がnilになる変数を扱う場合、if文などでnilを送信しないようにしてください。nilをpostするとエラーが出てしまいます。


fluentdの設定ファイルを作る

次に、fluentdの設定をしていきます。fluentdは起動させる時、初期設定では/etc/fluet/fluent.confを参照してそこに書いてある設定で動作します。
今回は練習ということもあるので、railsプロジェクトのconfig/フォルダにfluentフォルダを作って、そこにfluent.confの設定ファイルを作りたいと思います。

railsプロジェクトの中で

cd config/
mkdir fluent
cd fluent

でフォルダを作り、下のコマンドでfluent.confを作ります。

fluentd --setup ./

makefluentconf2

作成できましたね。


fluent.confを編集する

fluent.confをemacsとかvimで開いて、下の内容を一番下にでも書いておきます。

今回は単純にアクセスログをファイル出力する方法を行います。

<match user.access>
  type file
  path /var/log/fluent/user_access
  time_slice_format %Y%m%d
  time_slice_wait 10m
  time_format %Y%m%dT%H%M%S%z
  compress gzip
  utc
</match>

上の設定はuser.accessというタグが付いたデータが来たら、/var/log/fluent/というフォルダにuser_access+時間ファイルにデータを書き込むという意味になります。

恐らく、/var/log/fluent/フォルダが無いと思うので先に作成しましょう。
今は練習ですので、フォルダの権限を777にしてしまいましょう。

sudo mkdir /var/log/fluent/
sudo chmod 777 /var/log/fluent/

これでログを保存するフォルダができました。

fluentdを起動させる

railsプロジェクトのconfig/fluent/に移動します。

cd config/fluent/

fluent.confを確認して下のコマンド入力します。

fluentd -c ./fluent.conf -vv

止める時は「ctrl+c」で止められます。

fluentdが起動しました。


railsを実際に動かしてみる

これで準備が整いました。railsサーバを起動して、ブラウザからrailsにアクセスしてみましょう。

bundle exec rails s

deviseでログインしたり、ログインしない状態で適当にアクセスをしましょう。
oei

新しくコンソールを開いて、下のディレクトリに移動します。

cd /var/log/fluent/

fileexsist

ファイルが作成されていますね。

中身を除くと、データが保存されています。

fluentlog

うまくいきました。

本番環境以外は動作しないようにする

おまけですが、今回の様な書き方をすると本番環境以外でもデータを収集しようとします。
開発環境では別にfluentdにデータを投げる必要は無いと思います。
下のようにif文を書けば、本番環境でのみfluentdにデータを投げるので便利です。

Fluent::Logger::FluentLogger.open(nil, :host=>'localhost', :port=>24224) if Rails.env.production?
before_action :fluentpost if Rails.env.production?
def fluentpost
  if user_signed_in?
    Fluent::Logger.post("user.access",{"id"=>current_user.id,"user_name"=>current_user.email,"url"=>request.fullpath,"time"=>Time.now.to_s(:db)})
  else
    Fluent::Logger.post("user.access",{"id"=>"guest_id","user_name"=>"guest","url"=>request.fullpath,"time"=>Time.now.to_s(:db)})  
  end
end


まとめ

fluent-loggerをdeviseと掛け合わせると強力な情報収集ツールになります。これを使ってビックデータ分析などをやっていけるのではないでしょうか。

スポンサードリンク

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

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

執筆者:


comment

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

関連記事

railsのcarrierwaveとremotipartで画像のアップロードを非同期にしjsonを受け取る

概要 みなさんこんにちはcandleです。今回はremotipartとcarrierwaveを使って画像のアップロードをajax化したいと思います。 railsのフォームはremote設定をするだけで …

Chart.js 2.0でy軸の最大値(scales max)と最小値を設定する

概要 みなさんこんにちはcandleです。今回はChart.js2.0でy軸の最大値、最小値を設定する方法を紹介します。 Chart.js 2.0では特に指定しないと自動的に、y軸の最大値を設定してく …

railsのaws-sdk gemを使ってs3のファイルを削除する

by martinak15 概要 みなさんこんにちはcandleです。今回はs3にアップロードされている画像ファイルをrailsのaws-sdk gemを使用して削除してみたいと思います。 記事中で開 …

CakePHPでhelloworld

概要 CakePHPでプログラミングのお約束helloworldを行いましょう。 helloworldとは動作確認も含めた、一番最初に書くプログラムコードです。 だいたいはhello worldと単純 …

wordpressのwp_queryでpost投稿の記事一覧を取得する

概要 みなさんこんにちはcandleです。 最近はwordpressの開発を行っており、そこで、試行錯誤したwp_queryを使った記事一覧の取得の仕方を紹介します。wordpressは少し前まで、q …

  • English
  • 日本語

プロフィール


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

スポンサードリンク

アーカイブ