gpt4 book ai didi

Ruby - 在模块/类之间共享记录器实例

转载 作者:数据小太阳 更新时间:2023-10-29 06:21:53 24 4
gpt4 key购买 nike

正在编写一个小的 Ruby 脚本,该脚本可以访问网络并抓取各种服务。我有一个模块,里面有几个类:

module Crawler
class Runner
class Options
class Engine
end

我想在所有这些类中共享一个记录器。通常我只是将它放在模块中的常量中并像这样引用它:

Crawler::LOGGER.info("Hello, world")

问题是在我知道输出的去向之前我无法创建我的记录器实例。您通过命令行启动爬虫,此时您可以告诉它您想要在开发(日志输出到 STDOUT)或生产(日志输出到文件 crawler.log)中运行:

crawler --environment=production

我有一个类Options解析通过命令行传入的选项。只有到那时我才知道如何使用正确的输出位置实例化记录器。

因此,我的问题是:如何/将我的记录器对象放在哪里,以便我的所有类都可以访问它?

我可以将我的记录器实例传递给每个 new()调用我创建的每个类实例,但我知道必须有更好的 Rubyish 方式来做到这一点。我在想与 class << self 共享的模块上的一些奇怪的类变量或者其他魔法。 :)

更多细节:Runner通过将命令行选项传递给 Options 来启动一切类并返回一个带有几个实例变量的对象:

module Crawler
class Runner
def initialize(argv)
@options = Options.new(argv)
# feels like logger initialization should go here
# @options.log_output => STDOUT or string (log file name)
# @options.log_level => Logger::DEBUG or Logger::INFO
@engine = Engine.new()
end
def run
@engine.go
end
end
end

runner = Runner.new(ARGV)
runner.run

我需要 Engine 中的代码能够访问记录器对象(以及在 Engine 中初始化的更多类)。帮助!

如果您可以动态更改已经实例化的 Logger 的输出位置(类似于更改日志级别的方式),则可以避免所有这些情况。如果我在生产中,我会将它实例化为 STDOUT,然后切换到一个文件。我确实在某处看到了关于更改 Ruby 的 $stdout 全局变量的建议,这会将输出重定向到 STDOUT 以外的其他地方,但这看起来很老套。

谢谢!

最佳答案

我喜欢在我的类中使用 logger 方法,但我不喜欢在我的所有初始化器中散布 @logger = Logging.logger。通常,我这样做:

module Logging
# This is the magical bit that gets mixed into your classes
def logger
Logging.logger
end

# Global, memoized, lazy initialized instance of a logger
def self.logger
@logger ||= Logger.new(STDOUT)
end
end

然后,在你的类(class)中:

class Widget
# Mix in the ability to log stuff ...
include Logging

# ... and proceed to log with impunity:
def discombobulate(whizbang)
logger.warn "About to combobulate the whizbang"
# commence discombobulation
end
end

因为 Logging#logger 方法可以访问模块混入的实例,所以扩展您的日志记录模块以使用日志消息记录类名是微不足道的:

module Logging
def logger
@logger ||= Logging.logger_for(self.class.name)
end

# Use a hash class-ivar to cache a unique Logger per class:
@loggers = {}

class << self
def logger_for(classname)
@loggers[classname] ||= configure_logger_for(classname)
end

def configure_logger_for(classname)
logger = Logger.new(STDOUT)
logger.progname = classname
logger
end
end
end

您的 Widget 现在使用其类名记录消息,并且不需要更改一点:)

关于Ruby - 在模块/类之间共享记录器实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/917566/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com