0

可能重复:
在 Sinatra 中获取客户端的 IP 地址?

我将 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自动解析并将其放入日志中?


我按照一些答案中的建议尝试了以下方式:

配置.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

应用程序.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 }

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

4

2 回答 2

1

请参阅“ 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

哪个输出:

我,[2013-01-18T23:39:42.049072 #81011] INFO -- : 127.0.0.1: 请求“/”
127.0.0.1 - - [2013 年 1 月 18 日 23:39:42] “GET / HTTP/1.1” 200 31 0.0034

我可以继承 Logger 或对其进行修补,但我更喜欢将 logger 调用包装在本地方法中。我们在工作中的几个应用程序中使用它,并且效果很好。

于 2013-01-19T05:56:53.700 回答
-1

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

于 2013-01-18T19:25:55.273 回答