2006-02-10 優しいRailsの育て方 [長年日記]

[Rails] RSS でサーバ監視

運用サーバが死んでいたことに半日気付かなかった。当方、やんごとなき事情で ActiveRecord + DBI という変態プレイのために、ある程度のページ(AR)は動作するが、特定のページ(DBI)だけはエラーになるなんてことが稀に発生しちゃうのだ。エラーの原因は色々あって、なぜかある日突然接続できなくなったり、長期稼動時にFastCGIが腐っていたり、そもそもDBIのライブラリが消えてるという恐ろしいこともあった。(iDCがこっそり鯖を入れ替えたんじゃないのか?みたいな)。

で、そんな頻繁に起きるタイプの障害ではないのだが、最近立て続けに遭遇してしまったため、念のためにサーバを監視しておいた方がよさそうである。でも定期的にチェックするのも激しく面倒だし、そんな時間はない。2chや日記サイトとかは凄い頻度で見てるけどね。つーか、佐紀スレなんて5分おきにチェックして独占阻止してる気もするけど。。。いいの。それはいいの!とにかく、わざわざサーバを監視するのは何か面倒なの!何が違うんだろう。

  ノノハヽ∩ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ 
  川´・_・リ/< サーバの状態をRSSで見れるようにすればいいと思います
__ /    /  \______________________
\⊂ノ ̄ ̄ ̄\ 
||ヽ|| ̄ ̄ ̄ ̄ ̄|| 
 ...||  委員長  ||

フンガッ!!確かにそうすれば、頻繁なWebチェックの副作用で一緒にチェックできるんジャマイカ?

RSSを吐くコントローラ

status_controller.rb

require 'rss/maker'

class StatusController < ApplicationController
  ######################################################################
  ### Check classes
  class Check
    def initialize (name = nil, &block)
      @name  = name  || self.class.to_s
      @check = block || Proc.new{ check }
    end
    attr_reader :name, :passed, :message, :checked_on

    def execute
      @passed     = true
      @checked_on = Time.now
      @check.call
    rescue Exception => err
      @passed     = false
      @message    = err.to_s
    end
  end

  class ConnectViaDBI < Check
    def check
      config  = ActiveRecord::Base.configurations[::RAILS_ENV]
      adapter = "dbi:%s:%s" % [config['adapter'], config['database']]
      require 'dbi'
      DBI::connect(adapter, config['username'], config['password']).disconnect
    end
  end

  class PeacefulDay < Check
    def check
      error_count = Syslog.count("DATEDIFF(NOW(),created_on) < 1 AND priority > 10")
      raise "%d errors occurred !!" % error_count if error_count > 0
    end
  end

protected

  def checks
    [
     Check.new("ライブラリ 'digest/md5'") { require 'digest/md5'},
     Check.new("ActiveRecord からの接続") {ActiveRecord::Base.connection.active?},
     ConnectViaDBI.new("DBI からの接続"),
     PeacefulDay.new("今日も平和"),
    ]
  end

public
  ######################################################################
  ### Actions
  def index
    render :inline=>"<%= auto_discovery_link_tag :rss, :action => 'rss' %>"
  end
  
  def rss
    rss = RSS::Maker.make("1.0") do |maker|
      error_count  = 0
  
      checks.each_with_index do |check, i|
        check.execute
        item  = maker.items.new_item
        item.link            = url_for(:id=>i)
        item.description     = check.passed ? "OK" : "NG"
        item.title           = "[%s] %s" % [item.description, check.name]
        item.content_encoded = check.message.to_s
        item.date            = check.checked_on
        error_count += 1 unless check.passed
      end

      maker.channel.about       = url_for
      maker.channel.link        = url_for
      maker.channel.title       = "[%s] %s" % [(error_count > 0) ? "NG":"OK", url_for(:controller=>'')]
      maker.channel.description = "%d checks, %d failures" % [checks.size, error_count]
    end

    @headers["Content-Type"] = 'application/xml; charset=UTF-8'
    render :text => rss, :layout => false
  end
end

みたいなのを速攻ででっち上げ。各サーバに置いてみた。

server-status.png

あら、意外とよさげじゃない。RSSリーダで直接見てもいいし、多サーバ&自動化するときの中間コードとしても使えそうだし。HEAD とかの単なる ping でなくて、自分の欲しい情報を自由に取得できるのがいい感じだ。使い方はCheckインスタンスに処理を渡すか、長ければサブクラス化して、checks メソッドの中に入れるだけ。よかったらどうぞ。

Montastic

ふと嫌な予感がして、「RSS サーバ監視」あたりで検索してみたら「Montastic」というサーバ監視サービスがやっぱりありました。やはり凡人の考えなどお見通しですね。

アカウントは10秒で取得できて(*1)、AjaxなGUIでサーバを登録しておくと、異常があったらRSSやメールで通知してくれるみたいです。(メール送信先は5箇所指定可能)。そして、なにより無料なのが素晴らしいです。操作も直感的だし、Webでの確認ページも綺麗で好感触。

(*1) 項目も「メアド(通知用)」と「パスワード」のみ!

montastic.png

(↑存在しないページを指定してみた)

問題は、監視の更新のタイミングが指定できない点ぐらいかな。(10分固定?)。Webサーバの大筋の稼動状態はこれに任せて、マニアックなチェックはStatusControllerでやる、というハイブリッドな運用でしばらくやってみよう。

おまけ

直接 GET してくるみたい。

209.61.157.78 - - [10/Feb/2006:16:11:36 +0900] "GET /xxx HTTP/1.1" 404 201 "-" "montastic-webmonitor"

参考


サイト内検索 (by Google)

| JRuby | Rails | Berryz | ℃-ute | エッグ | jQuery |

過去

2006年
2月
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28

未来

コンタクト