如何使用请求ID标记rails中的每个日志调用(lograge)

时间:2015-04-20 18:06:12

标签: ruby-on-rails json logging

我正在使用带有rails的lograge,我已经使用JSON格式配置了我的日志。我希望每次拨打logger.infologger.warn等时都要包含请求uuid。 rails使用标记日志记录处理这种方式的方式达不到我想要的程度,因为它似乎无法将请求uuid与JSON有效负载的其余部分合并,而是将其以非JSON格式排在线上。

例如,如果我调用logger.info(client: :ig),我希望以下日志输出:

{"request_id": <request uuid>, "client": "ig"}

但是相反,rails会在请求uuid之前(通过config.log_tags = [:uuid]配置时),如下所示:

[<request uuid>] {"client": "ig"}

有没有人知道是否有办法让标记行为与JSON有效负载合并而不是将它预先放在同一行上?我想使用一个简单的JSON格式化器将我们的日志配置为转发到Splunk,而不是处理这种前置格式。

此外,我已将lograge配置为在request_id中传递给custom_options的lambda中将config/application.rb设置为请求uuid。这只有在rails记录请求时才有效。如果我在其他任何地方显式调用其中一个日志记录方法,则不包括request_id

# application.rb
config.lograge.enabled = true
config.lograge.formatter = Lograge::Formatters::Json.new
config.lograge.custom_options = lambda do |e|
  {
    params: e.payload[:params].except("controller", "action", "utf8"),
    request_id: e.payload[:request_id] # added this in `append_info_to_payload` in ApplicationController
  }
end

然后在config / environments / production.rb

config.log_tags = [ -> (req) { { request_id: req.env["action_dispatch.request_id"] } } ]

感谢任何帮助,谢谢。

2 个答案:

答案 0 :(得分:1)

问题是有效负载没有request_id。 正如您所见:

  

./ ActionPack的-3.2.11 / LIB / action_controller /金属/ instrumentation.rb:18-25

raw_payload = {
    :controller => self.class.name,
    :action     => self.action_name,
    :params     => request.filtered_parameters,
    :format     => request.format.try(:ref),
    :method     => request.method,
    :path       => (request.fullpath rescue "unknown")
  }

我重写此方法(在config / initializer.rb 中复制 ./ actionpack-3.2.11 / lib / action_controller / metal / instrumentation.rb)并添加PARAM。

raw_payload = {
    :controller => self.class.name,
    :action     => self.action_name,
    :params     => request.filtered_parameters,
    :format     => request.format.try(:ref),
    :method     => request.method,
    :path       => (request.fullpath rescue "unknown"),
    :request_id => env["action_dispatch.request_id"]
  }

也许有更好的方法来覆盖仪器,但这已经足够了。

答案 1 :(得分:0)

使用class_eval更容易覆盖初始化程序,如下所示: Access to Rails request inside ActiveSupport::LogSubscriber subclass