exception_notificationプラグインでクローラーからのアクセスによる例外を無視する

現在運用しているアプリにexception_notificationというプラグインを入れています。

これはproduction環境において、例外が発生した際に、その内容をメールで通知してくれるというものです。

とても便利なのですが、長いこと使っていて気になることがあります・・・

それは、クローラーからのアクセスによる例外がやたらと多いことです(´・ω・`)

放置すると例外通知メールがとんでもない量になってしまいます。


ということで、ちょっと前にこのプラグインに、「指定したクローラーがアクセスした時に発生する例外を無視」するように改修しました。
GitHub - tiwakawa/exception_notification: Exception Notifier Plugin for Rails

lib/exception_notifier.rb
     unless Array.wrap(options[:ignore_exceptions]).include?(exception.class)
-      Notifier.exception_notification(env, exception).deliver
-      env['exception_notifier.delivered'] = true
+      unless ignore_crawler_match?(env['HTTP_USER_AGENT'])
+        Notifier.exception_notification(env, exception).deliver
+        env['exception_notifier.delivered'] = true
+      else
+        Rails.logger.info "ExceptionNotifier ignored the exception by \"#{env['HTTP_USER_AGENT']}\""
+        Rails.logger.flush
+      end
     end

+  private
+  def ignore_crawler_match?(user_agent)
+    @options[:ignore_crawler].each do |crawler|
+      return true if !!(user_agent =~ Regexp.new(crawler))
+    end if @options[:ignore_crawler]
+    false
+  end

修正した箇所は上記の通りです。

ignore_crawler_match?というメソッドを追加し、その中で、
アクセスしたユーザーエージェントが、指定されたクローラー名と正規表現でマッチするか判定しています。

マッチしなかった場合は、通常とおりメールを送信します。
マッチした場合は、ログに「例外を無視した」旨を出力し、メールは送信されません。


設定方法は簡単です。

config/initializers/exception_notifier.rbといったファイル内で、
:ignore_crawlerオプションを指定するだけです。

MystyleMobile::Application.config.middleware.use ExceptionNotifier,
  :email_prefix => "[Whatever] ",
  :sender_address => %{"notifier" <notifier@example.com>},
  :exception_recipients => %w{exceptions@example.com},
  :ignore_crawler => %w{Y!J- Googlebot}

上記の例では
YahooのクローラーとGooglebotからのアクセスによる例外を無視できます。

これで、だいぶメールが少なくなりました。
この設定をしたアプリと、しないアプリを比べてみたら、現時点で送られてくるメール数が約20倍ほど違っていましたww


ちなみに、最近本家のexception_notificationプラグインを見てみたら、同様にクローラーによるアクセスを無視する処理が追加されていましたね。
Add :ignore_crawlers options. · smartinez87/exception_notification@2e36818 · GitHub

空のディレクトリをgitの管理対象にするには

中身がない空のディレクトリをgitの管理対象にしたい場合があります。
gitは空のディレクトリを管理対象としてくれません。

やり方は簡単で、管理対象にしたい空ディレクトリを作り、その中に.gitkeepを作成するだけです。

mkdir target
touch target/.gitkeep

これは.gitkeepに特別な意味があるわけではなく(と思っている)、ディレクトリの中身を作っているというだけですね(だと思う)。

前は.gitignoreでやっていたそうですが、ファイル名からみてもおかしいので、.gitkeepを使う方が良さそうですね。

参考にした記事

http://memo.yomukaku.net/entries/195

nkfを使って、ディレクトリ配下のファイルに存在する半角カナを全角カナに置換する

モバイルサイトを過去に作っていて、それをベースにスマホ用サイトも作るという流れになったのですが・・
モバイルサイトにある半角カナが、スマホサイトでは非常にうっとおしい(´;ω;`)
ということで、半角カナを全角カナに置換するという微妙な作業があったので、メモメモ。

結論として、このコマンドでいけました。

find ./ -name "*.erb" -exec nkf -w --overwrite {} \;

findで"*.erb"にマッチするファイルを検索し、それをnkfで全角カナに変換する。

ーwでUTF8に変換し、ーーoverwriteで上書きするという処理になります。
ーxをつけると変換処理が行われず、そのまま半角で出力されます。

ちなみにこの作業で、「nkf」が「Network Kanji Filter」だって知ったw

ページの下までスクロールされたことを検出する

最近のサイトは新しいデータを取得して表示するとき、ページネーション(「←前 1 2 3 次→」みたいなやつ)よりも、
ページが一番下までスクロールされたら処理するといった方法が多いように思います。
ちょっとクールだと思ったので、調べてやってみました。

コード

以下のようなコードで、思った通りの挙動になりました。

  // 垂直スクロール量を取得する
  var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;

  // 表示領域の高さを取得する
  var clientHeight = document.body.clientHeight;

  // スクロールバーで隠れた領域を含むコンテンツ領域の高さを取得する
  var scrollHeight = document.body.scrollHeight || document.docomentElement.scrollHeight;

  // Firefox・Chrome対応
  if(scrollHeight === clientHeight) {
    clientHeight = window.innerHeight;
  }

  // コンテンツ領域の底までの残り領域
  var remain = scrollHeight - clientHeight - scrollTop;

  // 一番下までスクロールされたら
  if(remain <= 0) {
    // 処理実行
  }

firefoxchromeで確認済み。

ただ、この仕組みを実装したサイトに、スマートフォンでアクセスすると問題ないのですが、
PCのブラウザでアクセスすると、処理が2回連続で動いてしまうという状況に・・・(´・ω・`)
(1回で終わるときもあれば、連続して動くこともある)

スクロールイベントにバインドさせている訳なんですが、おそらくスクロールイベントが連続する処理なので、
このような状況になっているのではないかと推測・・・詳細は不明・・・。

とりあえず、スマホ用のサイトだったので良しとします。