在Rails日志中包含参数/请求信息?

15

我试图在我的Rails日志中获取更多信息,特别是请求的URI或当前参数,如果可用的话(我们知道不总是有)。然而,我似乎做不到。这是我迄今为止所做的:

#config/environments/production.rb
config.logger = Logger.new(config.log_path)
config.log_level = :error
config.logger.level = Logger::ERROR

#config/environment.rb
class Logger
  def format_message(level, time, progname, msg)
    "**********************************************************************\n#{level} #{time.to_s(:db)} -- #{msg}\n"
  end  
end

我可以很好地自定义消息,但似乎无法在此处访问params / request变量。有人知道是否可能,如果可能的话该怎么做?或者是否有更好的方法来获取这些信息?(也许是基于Redis的东西?)

非常感谢,

Dan

3个回答

30

虽然这个问题已经很久没有回复了,但或许能帮到下一个遇到类似问题的人。

我刚刚做了类似的事情。

1) 你需要分别覆盖日志记录器和日志请求级别详情。看起来你已经弄清楚了如何自定义日志记录器。答案在这里: Rails logger format string configuration

2) 我记录了所有请求的请求和响应到我的服务中。请注意,Rails将大量内容放入标题中,因此直接转储请求或标题可能不是一个好主意。另外需要注意的是,我的应用程序主要通过API访问。如果你的应用程序主要是Web应用程序,我猜想大多数人都是如此,你可能不想检查response.body,因为它将包含你的HTML。

class ApplicationController < ActionController::Base 
  around_filter :global_request_logging
...
  def global_request_logging 
    http_request_header_keys = request.headers.keys.select{|header_name| header_name.match("^HTTP.*")}
    http_request_headers = request.headers.select{|header_name, header_value| http_request_header_keys.index(header_name)}
    logger.info "Received #{request.method.inspect} to #{request.url.inspect} from #{request.remote_ip.inspect}.  Processing with headers #{http_request_headers.inspect} and params #{params.inspect}"
    begin 
      yield 
    ensure 
      logger.info "Responding with #{response.status.inspect} => #{response.body.inspect}"
    end 
  end 
end

1
这正是我一直在寻找的。运行得很好。谢谢。 - Howler
这个回复太棒了!谢谢。 - Rafael Oliveira
2
实际上,只有当我将request.headers更改为request.headers.env时,它才对我起作用(我正在使用Rails 4)。提出了编辑建议。 - Medeiros
我认为你想要将 ("^HTTP.*") 改为 (/^HTTP.*/),但我也很好奇为什么你只匹配以 HTTP 开头的标头,除了说 Rails 添加了许多标头之外。Rails 没有添加的所有标头都以 HTTP 开头吗? - 0xtobit
String#match 可以使用以下任一语法 https://ruby-doc.org/core-2.4.0/String.html#method-i-match。是的,Rails 在其中放了很多实际上不会传输到网络的东西。当时,我并不知道客户端发送的标头中是否有未带 HTTP 前缀的内容。结果因人而异。 - John Hinnegan

3

这应该可以工作!:) 干杯。

logger.info({:user_agent => request.user_agent, :remote_ip => request.remote_ip}.inspect)

logger.info(params.inspect)

顺便说一下... 这应该放在您的控制器操作中。例如:如果您将其放置在create操作中,它还应记录用户代理(即浏览器)、远程IP(即用户的远程IP)和所有参数。


嗨Paddy,谢谢你。虽然这样可以工作,但是否有一种自动将请求/参数提供给记录器本身的方法?也就是说,如果不是我从控制器调用logger.info/warn/error,而是从代码中任何地方引发异常时调用它。例如,我可能在代码中调用了current_user.profesion.blank?这将导致错误,因为profesion应该是profession(未定义的nil函数等)。在日志中有url/当前参数以及堆栈跟踪将是很好的。 - Dan Hill
我尝试过了。但正如你所说,Logger在Rails加载之前已经配置好了。我找到了这篇文章,但我不知道它有多大帮助:http://www.ubuntusolutions.org/2009/08/custom-logger-in-rails.html - Shripad Krishna
是的。另一种方法可能是在调用Raise/logger的类/代码中进行扩展,以将一些额外的数据添加到消息中?甚至只是在ActionController中添加? - Dan Hill
这可能有助于解决参数问题。但仍然太啰嗦了。 ActionController::Base.logger = Logger.new(STDOUT) - Shripad Krishna

0

谢谢VP,但似乎不起作用。我认为,因为Logger在大多数Rails加载之前配置,所以它无法访问@env变量,也无法访问params / request变量。在format_message范围内,@env为空,request和request_uri也会出错。 - Dan Hill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接