Работа с небольшим Ruby script, который выходит в Интернет и сканирует различные сервисы. У меня есть модуль с несколькими классами внутри:
module Crawler
class Runner
class Options
class Engine
end
Я хочу поделиться одним регистратором среди всех этих классов. Обычно я просто помещал это в константу в модуль и ссылался так:
Crawler::LOGGER.info("Hello, world")
Проблема в том, что я не могу создать свой экземпляр журнала, пока не узнаю, куда идет выход. Вы запускаете сканер через командную строку, и в этот момент вы можете сказать, что хотите запустить его в разработке (выход журнала идет в STDOUT) или в производство (выход журнала идет в файл, crawler.log):
crawler --environment=production
У меня есть класс Options
, который анализирует параметры, переданные через командную строку. Только в этот момент я знаю, как создать экземпляр регистратора с правильным местоположением вывода.
Итак, мой вопрос: как/где я помещаю свой объект logger, чтобы все мои классы имели к нему доступ?
Я могу передать свой экземпляр журнала для каждого вызова 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, но это кажется довольно взломанным.
Спасибо!