Apache Access Log の SQL 解析

懸案だったApache Access Log を RDB に突っ込んで SQL で解析ってのもやっと片付いた。

調べてはみたんだがまさにそのもの、っていうのは見つからなかった。
その代り見つけたのがこれ。Apache の combined 形式のログをブッた切る perl の正規表現。

[ぴ] - Apache Combined Log を効率的にパースする正規表現メモ , Apache Combined Log 解析正規表現ベンチマークの補足 (2007/10/05) ,..

ここまであれば、あとは未だに perl の知識 0 な俺にでも書ける。

  1. #!/usr/bin/perl
  2. #
  3. # al2sql.pl: apache combind log to sql insert command translator
  4. #
  5. # usage:
  6. # al2sql.pl [tablename] < apache_log_file > sql_command_file
  7. #
  8. # table should be created as follows
  9. # create table MYAPACHELOG (HOST text, IDENT char(4), USER char(16), METHOD char(8), RESOURCE text, PROTO char(8), STATUS char(3), REFERER text, AGENT text, SEARCHSTR text, DOMAIN text, TIME datetime, BYTES int unsigned);
  10. "MYAPACHELOG"'Jan''Feb''Mar''Apr''May''Jun''Jul''Aug''Sep''Oct''Nov''Dec''/\'\'/g;
  11. ($host, $ident, $user, $time, $method, $resource, $proto, $status, $bytes, $re
  12. ferer, $agent)
  13. = ($_ =~ /^([^ ]*) ([^ ]*) ([^ ]*) \[([^]]*)\] "([^ ]*)(?: *([^ ]*) *([^
  14. ]*))?" ([^ ]*) ([^ ]*) "(.*?)" "(.*?)"/);
  15. $searchstr = "";
  16. if ($referer =~ /search\?/) {
  17. $S2 = $referer;
  18. $S2 =~ s/cache:[^\+]*\+//g;
  19. $S2 =~ s/&/ /g;
  20. $S2 =~ /[pq]=([^ ]*)/;
  21. $S3 = $1;
  22. $S3 =~ s/\+/ /g;
  23. $searchstr = nkf("-w --url-input", $S3);
  24. }
  25. $domain = "";
  26. if ($host !~ /^[0-9\.]*$/) {
  27. $domain = $host;
  28. $domain =~ s/^[^\.]*\.//;
  29. }
  30. $time =~ /(.*)\/(.*)\/([^:]*)(.*)/;
  31. $time = "$3-$month{$2}-$1$4";
  32. print "INSERT INTO $MYTABLENAME ";
  33. print "(HOST, IDENT, USER, TIME, METHOD, RESOURCE, PROTO, STATUS, BYTES, REFERER, AGENT, SEARCHSTR, DOMAIN) ";
  34. print "VALUES ('', '$ident', '', '', '', '', '$proto', '', '', '', '$agent', '', '') ";
  35. print ";\n";
  36. }

注意:31行目に&#38;というのが見えたら、それは blog エンジン側が勝手に & を変換してしまったものである。変換を抑制できなそうなので全角で書いておく。

search stringと hostname から domain の分離だけはここで頑張ってみた(時刻と日付も分離しといた方がいいかもだが…)。
これで insert 文が生成されるので、あとは db の方に流し込んでやればいい。 table は作り方は念の為冒頭のコメントに書いておいた。 db は sqlite でも mysql でもなんでも。 blog が mysql/postgresql 使ってたりすればそこに同居すればあとは sql 投げる php でも書けば終了。

念の為、この日記エントリについては creative commons ライセンスにしておくので再利用は御自由に。
Creative Commons License
This work is licensed under a Creative Commons Attribution-Share Alike 2.1 Japan License.

既に読み込んだログとの重複チェックは考えていない。日々 log rotate されているとして、前日分として切り分けられた分をその都度(cronででも) db に追加するスタイルなので、 log rotate よりも短いインターバルで db に登録したい人は下のエントリを参考に工夫してみて欲しい。

ApacheのログをDBで解析する - KamoLand

2009.5.10 追記: mysql が DD/MMM/YYYY フォーマットを読み込めないようなのでこちらで修正。


22:07:00 - 04.05.09 - kuroyagi - その他雑記 - 6245x