我们有代码在Ruby 1.8.6 Web应用程序中记录数据。你大致如下调用它:
$log.info("Some text here")
现在,在记录的输出中,我想要包含出现该行的模块。我知道Kernel#caller
将给我一个数组,我可以在其中提取日志行发生的文件和行号,但我不希望这样。我想要模块,而不是文件名。显而易见的解决方案是修改日志行,使其如下所示:
$log.info("Some text here", self.class.name)
然后解析结果。但是,这不会起作用,因为我试图在默认情况下提取此信息。也就是说,如果程序员忘记指定模块,那么我需要解决方案,这是日志行的第二个参数。
有没有办法做到这一点?如果没有,我将只需要处理caller
数组;我们的大多数模块都在不同的目录中,因此这将是一个80%的解决方案。
更完整的示例,请原谅轻微的语法错误:
文件log.rb中的:
module Log
class Logger
def info(msg, mod = '')
puts "Module: #{mod} Msg: #{msg}"
end
end # class Logger
end # module Log
$log = Log::Logger.new
在文件foo.rb中:
module Foo
class Bar
def do_something
# Do not pass in self.class.name.
# We want the output to look like:
# Module: Foo Msg: I did something!
$log.info "I did something!"
end
end # class Bar
end #module Foo
答案 0 :(得分:3)
使用call_stack。
首先使用RubyGems安装它:
gem install call_stack
然后将log.rb更改为:
require 'rubygems'
require 'call_stack'
call_stack_on
module Log
class Logger
def info(msg, mod = '')
mod = call_stack(2)[0][0] if mod == ''
puts "Module: #{mod} Msg: #{msg}"
end
end # class Logger
end # module Log
$log = Log::Logger.new
适合我(Ruby 1.8.7)。
$ ruby foo.rb
Module: Foo::Bar Msg: I did something!
答案 1 :(得分:3)
一个mixin解决了OP的具体要求(同时,为了解决通用的“谁叫我”的情况,给了Asher +1。)。
module Log
module Logger
def info(msg)
puts "Module: #{self} Msg: #{msg}"
end
end # class Logger
end # module Log
module Foo
class Bar
include Log::Logger
def do_something
# Do not pass in self.class.name.
# We want the output to look like:
# Module: Foo Msg: I did something!
info "I did something!"
end
end # class Bar
end # module Foo
foobar = Foo::Bar.new
foobar.do_something
答案 2 :(得分:2)
在为自己的目的寻找答案时遇到过这篇文章。
没有找到合适的,所以我挖掘了Ruby源并组合了一个扩展。我把它捆绑成一个gem-应该安装没有任何问题,只要你使用Ruby 1.9.1:
sudo gem install sender
这个对于Ruby 1.8不起作用,因为1.8有一个不同的跟踪帧模型。