アクセスログを眺めていて思ったんだが,ステータスコードでエラーを返している行を拾えば,便利なんじゃないだろうか.特に,404 Not Foundを拾うことができれば,サイト内のリンク切れをつぶすことができる.
そこで,スクリプトを改造,改造.
とりあえず,普通のログを吐くときとエラーログを吐くときに場合分けをするため,引数を取ることにした.ここで,CGIクラスとまた格闘してしまった(やっぱ,例文が欲しいよう).
begin
cgi = CGI.new
mode = cgi.params["mode"].to_s #モード取得
file = lastlog() #最新ファイル取得
logfile = open(file)
case mode
when "view"
log_view(file) #生ログ表示
when "error"
errorlog_view(file) #エラーログ表示
else
print "Content-Type: text/plain; charset=EUC-JP\n\n"
print "有効なモードを取得できません."
end
rescue StandardError
error_out()
rescue ScriptError
error_out()
end
error_out()は,エラーを表示してデバッグしやすくするための物で,『Ruby de CGI―Rubyで作るインタラクティブWebサイト』のものをそのまま持ってきている.
と,場合分けするところは比較的すぐにできたのだが,肝心のエラー表示部でエラく苦労してしまった.そのまま出力しても分かりにくいだろうからとステータスコード順に並べようとしたら,はまったのである.変数にとりあえずエラーの行を保持しようとハッシュのハッシュをいじっていたら,何がどれを指すやら分からなくなった上,型の違いではまった!う~ん,Rubyは型を気にしなくていいのね~と思っていたのが間違いの元でした.なんとか完成させたのが以下のコード.
def errorlog_view(file)
header_out("エラーログ")
logfile = open(file)
error = Hash.new
error_count = Hash.new
#エラー行を見つけてとりあえずハッシュに保持
while logline = logfile.gets
line = Accesslog.new(logline)
status = line.status
if /^[4|5]/ =~ status #ステータスコード400台と500台だけ処理
unless error.key?(status)
error[status] = Hash.new
error_count[status] = 0
end
error_count[status] += 1 #ステータスエラーのカウンター
#ステータスエラーの行を保持
error[status][error_count[status]] = line
end
end
error.sort.each{|status, value|
print "<h3>" + status.to_s + " " + STATUS[status] +"</h3>\n"
print "<ol>"
error_line = error[status]
error_line.sort.each{|count, line|
print "<li><dl class=\"log\">\n"
print "<dt>Access URI</dt><dd>#{line.requestURI}</dd>\n"
print "<dt>Datetime</dt><dd>#{line.year}年#{line.month}月#{line.day}日"
print "#{line.hour}時#{line.minute}分#{line.second}秒</dd>\n"
print "<dt>IP Address</dt><dd>#{line.ip}</dd>\n"
print "<dt>Referer</dt><dd>"
case line.referer
when "-"
print "(ダイレクトアクセス)</dd>\n"
else
print "<a href=\"#{line.referer}\">#{line.referer_unencode}</a></dd>\n"
end
print "<dt>User Agent</dt><dd>#{line.user_agent}</dd>\n"
print "</dl><hr>\n"
}
print "</ol>"
}
footer_out()
end
型違いではまったのは,「error[status] = Hash.new」のところ.ハッシュのハッシュを使っているので,ハッシュを入れとかなければいけないのに,""を入れていた.これだと文字列なんだよね…….
lineの保持さえうまくいけば,表示するところは簡単.並べ替えて全部表示する.STATUSという定数はハッシュで,ステータスコードをエラーメッセージにするための物.
#ステータスコードをメッセージにするためのハッシュ定数
STATUS = {"400" => "Bad Request",
"401" => "Unauthorized",
"402" => "Payment Required",
"403" => "Forbidden",
"404" => "Not Found",
"405" => "Method Not Allowed",
"406" => "Not Acceptable",
"407" => "Proxy Authentication Required",
"408" => "Request Timeout",
"409" => "Conflict",
"410" => "Gone",
"411" => "Length Required",
"412" => "Precondition Failed",
"413" => "Request Entity Too Large",
"414" => "Request-URI Too Long",
"415" => "Unsupported Media Type",
"416" => "Requested Range Not Satisfiable",
"417" => "Expectation Failed",
"500" => "Internal Server Error",
"501" => "Not Implemented",
"502" => "Bad Gateway",
"503" => "Service Unavailable",
"504" => "Gateway Timeout",
"505" => "HTTP Version Not Supported"
}
400番台と500番台をここで拾うようにしたので,生ログ出力では拾わないことにした.
しまった,robots.txtとか/MSOffice/cltreq.asp~とか/favicon.icoは省いた方がよかったかなぁ.
ちなみに,robots.txtはロボット型検索エンジンのロボットさんが探しに来る物で,行儀のいいロボットならこのファイルの指示にしたがってくれる.MSOfficeなんたらかんたらは,IE+MS Office環境でWebディスカッション機能が有効になっていると探しに来るんだったと記憶する.で,favicon.icoはご存じ,IEなんかのお気に入りで表示されるアイコン.faviconのログは何か遊べそうだなあ.ちょっと調べてみるか.