SDB logger for apache を作ってみた

apacheのログをSimpleDBに保存するスクリプトを作ってみました。

発端

本日行われたwebセミナーでSDBにログを保存する的な話の流れからとんだ無茶振りが。
http://twitter.com/dateofrock/statuses/70408270497595392

受けて立つしか!

設計

apacheから、pipeで1行渡して、SimpleDBに放り込むだけの簡単なお仕事なので、

  1. apacheからどうやってデータを渡すか
  2. 渡されたデータをどうやってパースするか
  3. パースしたデータをどうやってSimpleDBに入れるか

を考える。

  1. についてはCombinedログを使ってるサイトが多いと思ったので、それをベースに。
  2. でパースを簡単にするために、スペース区切りではなくtab区切りにしてしまいました
  3. right_awsのsdb_interfaceおいしいです。

実装

使ったのはUbuntuのapache2です。
/etc/apache2/apache2.confに以下の設定を適当な場所に追加。

LogFormat "%h\t%l\t%u\t%t\t\"%r\"\t%>s\t%O\t\"%{Referer}i\"\t\"%{User-Agent}i\"" combined_tabbed

デフォルトのvirtual hostのロギング設定を変更。
/etc/apache2/sites-enabled/000-default

#       CustomLog ${APACHE_LOG_DIR}/access.log combined
        CustomLog "| /path/to/sdblogger.rb " combined_tabbed

スクリプトはざっくりこんな感じ。必要なattributesは自分で追加して下さい。

#!/usr/bin/env ruby
require 'rubygems'
require 'right_aws'

sdb = RightAws::SdbInterface.new('ACCESSKEY','SECRETKEY',{:multi_thread => true} )

while s = gets
  p=s.split(/\t/)
  attributes={}
  attributes['host']=p[0]
  attributes['request']=p[4]
  sdb.put_attributes 'sdblogger', p[3] , attributes
end

何度かアクセスしてデータを見てみます。ちゃんと保存されてますね。

<?xml version="1.0"?>
<SelectResponse xmlns="http://sdb.amazonaws.com/doc/2009-04-15/">
  <SelectResult>
    <Item>
      <Name>[17/May/2011:09:30:58 +0000]</Name>
      <Attribute>
        <Name>host</Name>
        <Value>xxx.46.114.90</Value>
      </Attribute>
      <Attribute>
        <Name>request</Name>
        <Value>"GET / HTTP/1.1"</Value>
      </Attribute>
    </Item>
    <Item>
      <Name>[17/May/2011:09:30:59 +0000]</Name>
      <Attribute>
        <Name>host</Name>
        <Value>xxx.46.114.90</Value>
      </Attribute>
      <Attribute>
        <Name>request</Name>
        <Value>"GET / HTTP/1.1"</Value>
      </Attribute>
    </Item>
    <Item>
      <Name>[17/May/2011:09:31:00 +0000]</Name>
      <Attribute>
        <Name>host</Name>
        <Value>xxx.46.114.90</Value>
      </Attribute>
      <Attribute>
        <Name>request</Name>
        <Value>"GET / HTTP/1.1"</Value>
      </Attribute>
    </Item>
  </SelectResult>
  <ResponseMetadata>
    <RequestId>ccc3dfaa-68ae-4119-b7a7-7af410f57eae</RequestId>
    <BoxUsage>0.0000594282</BoxUsage>
  </ResponseMetadata>
</SelectResponse>