使用 Log4r 进行上下文日志记录
以下是我现有的 Log4r 日志记录代码的工作原理。正如您在 WorkerX::a_method 中看到的,每当我记录消息时,我都希望包含类名和调用方法(我不希望所有调用者历史记录或任何其他噪音,这是我背后的目的LgrHelper)。
class WorkerX
include LgrHelper
def initialize(args = {})
@logger = Lgr.new({:debug => args[:debug], :logger_type => 'WorkerX'})
end
def a_method
error_msg("some error went down here")
# This prints out: "WorkerX::a_method - some error went down here"
end
end
class Lgr
require 'log4r'
include Log4r
def initialize(args = {}) # args: debug boolean, logger type
@debug = args[:debug]
@logger_type = args[:logger_type]
@logger = Log4r::Logger.new(@logger_type)
format = Log4r::PatternFormatter.new(:pattern => "%l:\t%d - %m")
outputter = Log4r::StdoutOutputter.new('console', :formatter => format)
@logger.outputters = outputter
if @debug then
@logger.level = DEBUG
else
@logger.level = INFO
end
end
def debug(msg)
@logger.debug(msg)
end
def info(msg)
@logger.info(msg)
end
def warn(msg)
@logger.warn(msg)
end
def error(msg)
@logger.error(msg)
end
def level
@logger.level
end
end
module LgrHelper
# This module should only be included in a class that has a @logger instance variable, obviously.
protected
def info_msg(msg)
@logger.info(log_intro_msg(self.method_caller_name) + msg)
end
def debug_msg(msg)
@logger.debug(log_intro_msg(self.method_caller_name) + msg)
end
def warn_msg(msg)
@logger.warn(log_intro_msg(self.method_caller_name) + msg)
end
def error_msg(msg)
@logger.error(log_intro_msg(self.method_caller_name) + msg)
end
def log_intro_msg(method)
msg = class_name
msg += '::'
msg += method
msg += ' - '
msg
end
def class_name
self.class.name
end
def method_caller_name
if /`(.*)'/.match(caller[1]) then # caller.first
$1
else
nil
end
end
end
我真的不喜欢这种方法。我宁愿只使用现有的 @logger 实例变量来打印消息并足够聪明地了解上下文。如何才能完成这个或类似的更简单的方法?
我的环境是 Rails 2.3.11(目前!)。
Here's how some of my existing logging code with Log4r is working. As you can see in the WorkerX::a_method, any time that I log a message I want the class name and the calling method to be included (I don't want all the caller history or any other noise, which was my purpose behind LgrHelper).
class WorkerX
include LgrHelper
def initialize(args = {})
@logger = Lgr.new({:debug => args[:debug], :logger_type => 'WorkerX'})
end
def a_method
error_msg("some error went down here")
# This prints out: "WorkerX::a_method - some error went down here"
end
end
class Lgr
require 'log4r'
include Log4r
def initialize(args = {}) # args: debug boolean, logger type
@debug = args[:debug]
@logger_type = args[:logger_type]
@logger = Log4r::Logger.new(@logger_type)
format = Log4r::PatternFormatter.new(:pattern => "%l:\t%d - %m")
outputter = Log4r::StdoutOutputter.new('console', :formatter => format)
@logger.outputters = outputter
if @debug then
@logger.level = DEBUG
else
@logger.level = INFO
end
end
def debug(msg)
@logger.debug(msg)
end
def info(msg)
@logger.info(msg)
end
def warn(msg)
@logger.warn(msg)
end
def error(msg)
@logger.error(msg)
end
def level
@logger.level
end
end
module LgrHelper
# This module should only be included in a class that has a @logger instance variable, obviously.
protected
def info_msg(msg)
@logger.info(log_intro_msg(self.method_caller_name) + msg)
end
def debug_msg(msg)
@logger.debug(log_intro_msg(self.method_caller_name) + msg)
end
def warn_msg(msg)
@logger.warn(log_intro_msg(self.method_caller_name) + msg)
end
def error_msg(msg)
@logger.error(log_intro_msg(self.method_caller_name) + msg)
end
def log_intro_msg(method)
msg = class_name
msg += '::'
msg += method
msg += ' - '
msg
end
def class_name
self.class.name
end
def method_caller_name
if /`(.*)'/.match(caller[1]) then # caller.first
$1
else
nil
end
end
end
I really don't like this approach. I'd rather just use the existing @logger instance variable to print the message and be smart enough to know the context. How can this, or similar simpler approach, be done?
My environment is Rails 2.3.11 (for now!).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
使用
extend
发布我的答案后(请参阅下面的“编辑”),我想我应该尝试使用set_trace_func
来保留某种堆栈跟踪就像我发布的讨论中一样。这是我的最终解决方案;set_trace_proc
调用将被放入初始化程序或类似的程序中。我不知道对 proc 的调用会在多大程度上(如果有的话)影响应用程序的性能;如果它最终成为一个问题,也许调用类的一些不那么智能的东西(就像下面我的旧答案)会更好。
[编辑:以下是我的旧答案,上面引用了。]
使用
延长
?这是我根据您的代码编写的一个快速而肮脏的脚本来测试它;我必须重新排序以避免错误,但代码是相同的,除了LgrHelper
(我将其重命名为CallingMethodLogger
)和第二行WorkerX< /code> 的初始化程序:
输出为:
缺点是,通过此方法,不会自动计算出调用者的类名;它是基于传递到
Lgr
实例的@logger_type
显式的。但是,您也许可以使用另一种方法来获取类的实际名称 - 也许类似于 call_stack gem< /a> 或使用Kernel#set_trace_func
--参见此线程。After posting my answer using
extend
, (see "EDIT", below), I thought I'd try usingset_trace_func
to keep a sort of stack trace like in the discussion I posted to. Here is my final solution; theset_trace_proc
call would be put in an initializer or similar.I don't know how much, if any, the calls to the proc will affect the performance of an application; if it ends up being a concern, perhaps something not as intelligent about the calling class (like my old answer, below) will work better.
[EDIT: What follows is my old answer, referenced above.]
How about using
extend
? Here's a quick-and-dirty script I put together from your code to test it out; I had to reorder things to avoid errors, but the code is the same with the exception ofLgrHelper
(which I renamedCallingMethodLogger
) and the second line ofWorkerX
's initializer:The output is:
The downside is, via this method, the caller's class name isn't automatically figured out; it's explicit based on the
@logger_type
passed into theLgr
instance. However, you may be able to use another method to get the actual name of the class--perhaps something like the call_stack gem or usingKernel#set_trace_func
--see this thread.