LoginSignup
25
25

More than 5 years have passed since last update.

Ruby/RackでログをLTSVで出す

Last updated at Posted at 2013-03-26

今更感が強いですが実際ログをLTSVにすると扱いやすい場面に最近遭遇したので。

ltsv_formatter.rb
require 'logger'

class Logger
  class FreeFormatter < Formatter
    Format = "%{label}, [%{time}#%{pid}] %<severity>5s -- %{progname}: %{message}\n"

    attr_accessor :format

    def initialize(format=self.class::Format)
      @format = format || Format
      super()
    end

    def call(severity, time, progname, msg)
      @format % {
        :label => severity[0..0],
        :time => format_datetime(time),
        :pid => $$,
        :severity => severity,
        :progname => progname,
        :message => msg2str(msg)
      }
    end
  end

  class LTSVFormatter < FreeFormatter
    Format = %w[severity time progname pid message].map {|field|
      "#{field}:%{#{field}}"
    }.join("\t") + "\n"

    private

    def format_datetime(time)
      if @datetime_format.nil?
        time.strftime("%Y-%m-%dT%H:%M:%S.") << "%06d" % time.usec
      else
        super
      end
    end
  end
end

if __FILE__ == $0
  logger = Logger.new($stderr)
  logger.formatter = Logger::FreeFormatter.new
  logger.debug 'hello'
  logger.info 'world'
  logger.formatter = Logger::LTSVFormatter.new
  logger.warn 'hi'
  logger.error 'again'
end
ltsv_logger.ru
class LTSVLogger < Rack::CommonLogger
  FORMAT = %w[host user time method path query version status size].map {|field| "#{field}:%{#{field}}"}.join("\t") + "\truntime:%<runtime>0.4f\n"

  def log(env, status, header, began_at)
    now = Time.now
    length = extract_content_length(header)

    logger = @logger || env['rack.errors']
    logger.write FORMAT % {
      host:    env['HTTP_X_FORWARDED_FOR'] || env["REMOTE_ADDR"] || "-",
      user:    env["REMOTE_USER"] || "-",
      time:    now.strftime("%d/%b/%Y %H:%M:%S"),
      method:  env["REQUEST_METHOD"],
      path:    env["PATH_INFO"],
      query:   env["QUERY_STRING"].empty? ? "" : "?"+env["QUERY_STRING"],
      version: env["HTTP_VERSION"],
      status:  status.to_s[0..3],
      size:    length,
      runtime: now - began_at }
  end
end

use LTSVLogger
run lambda {|env|
  [200, {'Content-Type' => 'text/plain'}, ['Hello, LTSV']]
}
25
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
25