Rob*_*ron 48 ruby logging class-design
处理一个小的Ruby脚本,该脚本可以访问Web并抓取各种服务.我有一个包含几个类的模块:
module Crawler
class Runner
class Options
class Engine
end
Run Code Online (Sandbox Code Playgroud)
我想在所有这些类中共享一个记录器.通常我只是将它放在模块中的常量中并像这样引用它:
Crawler::LOGGER.info("Hello, world")
Run Code Online (Sandbox Code Playgroud)
问题是,在我知道输出的位置之前,我无法创建我的记录器实例.您可以通过命令行启动爬网程序,此时您可以告诉它您要在开发中运行(日志输出转到STDOUT)或生产(日志输出转到文件,crawler.log):
crawler --environment=production
Run Code Online (Sandbox Code Playgroud)
我有一个类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
Run Code Online (Sandbox Code Playgroud)
我需要代码Engine
才能访问logger对象(以及更多内部初始化的类Engine
).救命!
如果您可以动态更改已实例化的Logger的输出位置(类似于更改日志级别的方式),则可以避免所有这些.我将它实例化为STDOUT,然后如果我正在制作中则转换为文件.我确实看到了一个关于更改Ruby的$ stdout全局变量的建议,这会将输出重定向到除STDOUT之外的某个地方,但这看起来很糟糕.
谢谢!
Jac*_*cob 99
我喜欢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
Run Code Online (Sandbox Code Playgroud)
然后,在你的课程中:
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
Run Code Online (Sandbox Code Playgroud)
因为该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
Run Code Online (Sandbox Code Playgroud)
您Widget
现在使用其类名记录消息,并且不需要更改一位:)
Chu*_*uck 22
根据您已经设计的设计,看起来最简单的解决方案是为Crawler提供一个返回模块ivar的模块方法.
module Crawler
def self.logger
@logger
end
def self.logger=(logger)
@logger = logger
end
end
Run Code Online (Sandbox Code Playgroud)
或者你可以使用" class <<self
魔法",如果你想:
module Crawler
class <<self
attr_accessor :logger
end
end
Run Code Online (Sandbox Code Playgroud)
它完全一样.
ped*_*edz 13
正如Zenagray所指出的那样,从类方法中记录下来的是雅各布的回答.一个小的补充解决了:
require 'logger'
module Logging
class << self
def logger
@logger ||= Logger.new($stdout)
end
def logger=(logger)
@logger = logger
end
end
# Addition
def self.included(base)
class << base
def logger
Logging.logger
end
end
end
def logger
Logging.logger
end
end
Run Code Online (Sandbox Code Playgroud)
预期用途是通过"包括":
class Dog
include Logging
def self.bark
logger.debug "chirp"
puts "#{logger.__id__}"
end
def bark
logger.debug "grrr"
puts "#{logger.__id__}"
end
end
class Cat
include Logging
def self.bark
logger.debug "chirp"
puts "#{logger.__id__}"
end
def bark
logger.debug "grrr"
puts "#{logger.__id__}"
end
end
Dog.new.bark
Dog.bark
Cat.new.bark
Cat.bark
Run Code Online (Sandbox Code Playgroud)
生产:
D, [2014-05-06T22:27:33.991454 #2735] DEBUG -- : grrr
70319381806200
D, [2014-05-06T22:27:33.991531 #2735] DEBUG -- : chirp
70319381806200
D, [2014-05-06T22:27:33.991562 #2735] DEBUG -- : grrr
70319381806200
D, [2014-05-06T22:27:33.991588 #2735] DEBUG -- : chirp
70319381806200
Run Code Online (Sandbox Code Playgroud)
请注意,记录器的ID在所有四种情况下都是相同的.如果你想为每个类创建一个不同的实例,那么不要使用Logging.logger
,而是使用self.class.logger
:
require 'logger'
module Logging
def self.included(base)
class << base
def logger
@logger ||= Logger.new($stdout)
end
def logger=(logger)
@logger = logger
end
end
end
def logger
self.class.logger
end
end
Run Code Online (Sandbox Code Playgroud)
同样的程序现在产生:
D, [2014-05-06T22:36:07.709645 #2822] DEBUG -- : grrr
70350390296120
D, [2014-05-06T22:36:07.709723 #2822] DEBUG -- : chirp
70350390296120
D, [2014-05-06T22:36:07.709763 #2822] DEBUG -- : grrr
70350390295100
D, [2014-05-06T22:36:07.709791 #2822] DEBUG -- : chirp
70350390295100
Run Code Online (Sandbox Code Playgroud)
请注意,前两个id是相同的,但与前两个id不同,表明我们有两个实例 - 每个类一个.
归档时间: |
|
查看次数: |
25640 次 |
最近记录: |