在使用 Rails 3.2 进行日志记录时,如何记录日志语句发生的文件名和行号?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在使用 Rails 3.2 进行日志记录时,如何记录日志语句发生的文件名和行号?相关的知识,希望对你有一定的参考价值。

当使用 Rails 3.2 进行日志记录时,我想记录日志记录发生的文件名和行号。

因此,如果在我的ruby脚本中 customer.rb 在线 23 我有一个日志,像。

Rails.logger.debug "Debug message"

我想让日志记录一些东西

[customer.rb:23] Debug message

这可能吗?

答案

我终于发现,最好的解决方案是如下,这也会影响到我的应用程序所使用的其他gems的日志格式。

  1. 打开类 Logger::SimpleFormatter 并覆盖该方法 call. 你可以在一个初始化文件(config/initializers).
  2. 改变方法 call 中的文件和行进行记录。caller[5].

下面是一个对我来说很有效的实现示例。

class Logger::SimpleFormatter
  def call(severity, time, progname, msg)
    call_details = Kernel.caller[5].gsub(/#{Rails.root}/, '')
    call_details.match /(.+):(.+):/
    filename = $1
    line = $2
    length = 40
    filename = "#{filename[-length, filename.length]}" if filename.length >= length
    filename = filename.rjust(length + 2, '.')
    "[#{severity} #{time} #{filename}:#{line}] #{msg}
"
  end
end

在我上面的解决方案中,我也将文件名限制在最后40个字符,这样我就可以避免打印大的文件路径。

另一答案

当然,最简单的解决方案是在你的代码中使用__LINE__和__FILE__作为你的消息的一部分,但我猜想你想改变你的记录器的格式选项。我不知道在日志格式化器中有什么直接的方法,但是,如果你想使用一些自定义规则来过滤日志。标签:伐木 在Active upport中,通过在日志行中标明子域、请求ID和其他任何东西来帮助调试这样的应用程序,从而帮助您做到这一点。你可以使用__FILE__和__LINE__变量来代替标签,这里有一个例子。

logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
logger.tagged("BCX") { logger.info "Stuff" }                            # Logs "[BCX] Stuff"
logger.tagged("BCX", "Jason") { logger.info "Stuff" }                   # Logs "[BCX] [Jason] Stuff"
logger.tagged("BCX") { logger.tagged("Jason") { logger.info "Stuff" } } # Logs "[BCX [Jason] Stuff

我还建议你像下面的例子一样改变formatter。

Log = Logger.new(STDOUT)
  Log.formatter = proc { |severity, datetime, progname, msg|
    "#{severity} #{caller[4]} #{msg}
"
  }

现在每次调用 Log.INFO( 'some message')时,你应该有日志方法的 "调用者 "的文件和行号。

另一答案

我可以在环境配置中尝试以下几行内容 config/environments/....rb:

config.log_formatter = proc { |severity, datetime, progname, msg|
  callee = caller[5]                         # get caller from stack
  callee = callee.split('/').last            # remove path from callee info
  callee = callee.split(':')[0, 2].join(':') # remove method name from info

  "[#{callee}] #{msg}
"
}

注意:这取决于你的Rails版本,你将在Rails的文件名和行号中找到正确的文件。caller 栈。在写这篇文章的时候,我发现所要求的信息是在 caller[5] 在堆栈中,其他版本可能在其他位置上有它。因此这种方法不是很靠谱,将来你更新Rails版本的时候肯定会坏掉。

我看到的问题。仅仅有一个文件名真的有用吗?如何处理来自Rails本身的日志消息?如何测试以确保堆栈跟踪中的位置在以后的Rails版本中能保持正确?

文件名和行号作为日志格式的默认值真的好吗?我不这么认为。

以上是关于在使用 Rails 3.2 进行日志记录时,如何记录日志语句发生的文件名和行号?的主要内容,如果未能解决你的问题,请参考以下文章

程序员如何科学地记日志

如何在独立的日志文件中记录 Rails 中的某些内容?

如何在 Rails 开发中忽略延迟作业查询日志记录

无法在 Rails 3.2 中使用复合唯一索引将记录添加到连接表

如何在 RSpec 测试中为 ActiveRecord 打开 SQL 调试日志记录?

Ruby-on-Rails 3.2:导出包含大型数据集(100,000 条记录)的 CSV