如何始终使用记录器记录IP?

时间:2013-01-18 18:49:20

标签: ruby logging sinatra

  

可能重复:
  Get client’s IP address in Sinatra?

我正在将Sinatra与Apache和Passenger一起使用。

我目前在config.ru中使用以下记录器:

LOGGER = Logger.new("logs/sinatra.log")

我可以使用以下方式在我的应用中记录内容:

LOGGER.error "Log msg"

示例日志条目如下所示:

E, [2013-01-18T19:43:41.857146 #19412] ERROR -- : Log msg

如何将当前用户的IP放入日志中,因此它可能如下所示:

E, [2013-01-18T19:43:41.857146 #19412] ERROR -- : <127.0.0.1> Log msg

我可以写:

LOGGER.error "<#{request.ip}> Log msg"

但是,我想在每条日志消息上都有它,所以总是手动预先设置IP似乎是错误的方式。如何LOGGER配置为自动解析request.ip并将其放入日志中?


我按照以下方式尝试了一些答案:

configure.ru:

configure do
    LOGGER = Logger.new("logs/sinatra.log")
    original_formatter = Logger::Formatter.new
    LOGGER.formatter = proc { |severity, datetime, progname, msg|
        original_formatter.call(severity, datetime, progname, "#{ip} #{msg.dump}")
    }
end

app.rb:

helpers do
    def ip
        request.ip
    end
end

get '/' do
    LOGGER.info 'test'
end

结果如下:

NameError: undefined local variable or method `ip' for #<Rack::Builder:0x00000001821c60>

更新根据TheTinMan的回答,我提出了以下帮助:

helpers do
    def log(call,msg = '')
        severity = Logger.const_get(call.upcase)
        return if LOGGER.level > severity

        msg = yield if block_given?
        LOGGER.send(call, "<#{request.ip}> #{msg}")
    end
end

所以我可以这样做:

log :info, 'msg'
log(:debug) { very.expensive.operation }

这看起来像我想要的解决方案。还有改进的余地吗?

2 个答案:

答案 0 :(得分:1)

请参阅“Simple and Ideal Logging in Sinatra”:

我倾向于使用类似的东西:

require 'sinatra'
use Rack::Logger

def log(msg)
  logger.info('%s: %s' % [request.ip, msg])
end

get '/' do
  log("Request for '/'")
  '<html><body>psych</body></html>'
end

哪个输出:

I, [2013-01-18T23:39:42.049072 #81011]  INFO -- : 127.0.0.1: Request for '/'
127.0.0.1 - - [18/Jan/2013 23:39:42] "GET / HTTP/1.1" 200 31 0.0034

我可以对Logger进行子类化,或对其进行修补,但我更喜欢在本地方法中包装记录器调用。我们在工作中的几个应用程序中使用它,并且它工作得很好。

答案 1 :(得分:-1)

您可以覆盖Logger的格式化程序。有关示例,请参阅http://www.ruby-doc.org/stdlib-1.9.3/libdoc/logger/rdoc/Logger.html。 您可以创建一个sinatra帮助器方法来返回请求IP,以便可以从formatter proc调用它。