こちらの記事で書いた、Apacheのログを生成し続けるスクリプトをRubyGemsに登録してみました。
なので、今後は
gem install apache-loggen
とインストールするだけで、
apache-loggen
というコマンドが使えるようになります。使い方は今までと同じです。(以下のような感じです)
apache-loggen [--rate=0] [--limit=0] [--rotate=0] [--progress] [--json] [outfile]
--rate 毎秒何レコード生成するかの指定。0以下は制限無し。 --limit 最大何件出力するか。0以下は延々と出力し続ける。 --rotate ローテーションの間隔。単位は秒指定。0以下はローテーションしない。 --progress STDERRに経過情報を出力する --json apacheのログ形式ではなくJSON形式で出力する outfile 指定するとファイルに出力します。省略するとSTDOUTに出力します。
毎秒10件をaccess.logに出力。60秒毎にローテーション。経過をSTDERRに表示。
apache-loggen --rate=10 --rotate=60 --progress access.log
また、この機構を使って独自のログ形式を出力できるようにしました。 以下のように使います。
require 'apache-loggen/base' LogGenerator.generate(conf=nil, gen_obj=nil, &block)
confはnilを渡すとARGVの内容をパースします。プログラムで直接指定する場合は、Hashを渡す事でデフォルトの設定を上書きする事ができます。実際にログを出力する処理は、gen_objにLogGenerator::Baseを継承しgenerate(context, config)メソッドを定義したクラスのインスタンスを渡すか、ブロックを与えます。両方指定した場合は、gen_objが先に実行され、blockが評価されます。(blockではgen_objで出力したrecordを受け取る事ができます)
いくつかサンプルを置いておきます。
独自のログ形式を出力したい場合。
require 'apache-loggen/base' class MyGen < LogGenerator::Base def generate(context, config) return "#{Time.now.to_s} #{context.inspect}\n" end end LogGenerator.generate(nil, MyGen.new)
もしくは
require 'apache-loggen/base' LogGenerator.generate do | context, config, record | "#{Time.now.to_s} #{context.inspect}\n" end
上記の2つは同じ処理です。
Apacheログに新しく情報を追加したい場合。
require 'apache-loggen/base' class MyGen < LogGenerator::Apache # オリジナル実装はhashをJSONか1行の文字列にしているが # 今回はそれに情報を追加する def format(record, config) record["process_time"] = grand(1000000) + 1000 if config[:json] then return record.to_json + "\n" else return %[#{record['host']} - #{record['user']} [#{Time.now.strftime('%d/%b/%Y:%H:%M:%S %z')}] "#{record['method']} #{record['path']} HTTP/1.1" #{record['code']} #{record['size']} "#{record['referer']}" "#{record['agent']}" #{record['process_time']}\n] end end end LogGenerator.generate(nil, MyGen.new)
LogGenerator::ApacheはLogGenerator::Baseを継承しており、generateの中でformatを呼び出しています。このformatの実装が、1行分のレコードをhashとしてうけとりJSONか1行の文字列に変換するという処理をしているので、これをOverrideするとApacheログの生成ロジックを使いつつ書式を変更する事ができます。
いくつかのサンプルはREADMEにも書いてあります。
(∩´∀`)∩