Если вы создаете регистратор самостоятельно, вы можете сначала создать объект File
, а затем использовать его для создания регистратора и присвоить ему $stderr
:
log_file = File.new('foo.log', 'a')
logger = Logger.new(log_file, 'weekly')
$stderr = log_file #usually no need to use reopen
Обратите внимание, что это приведет к тому, что вывод журнала будет смешан с выводом $stderr
, что может вызвать проблемы, если вы анализируете файл журнала, ожидая, что он будет в определенном формате (это произойдет с вашим решением тоже).
Если у вас нет базового файла, а просто получите logger
откуда-то еще, это немного сложнее. Требуется IO
подобный объект, который может быть назначен на $stderr
и передает все записанное в него регистратору. Класс IO
в Ruby, к сожалению, довольно тесно связан с базовой системой ввода-вывода (файловые дескрипторы и т. П.), И нет общего интерфейса, который можно использовать для создания потоков ввода и вывода. (StringIO
является заметным исключением).
Однако большинство, если не все, методы вывода в IO
в конечном итоге проходят через #write
, поэтому, переопределив этот единственный метод, вы можете приблизиться к тому, что вам нужно:
class IOToLog < IO
def initialize(logger)
@logger = logger
end
def write(string)
#assume anything written to stderr is an error
@logger.error(message)
end
end
logger = get_logger_from_somewhere
$stderr = IOToLog.new(logger)
Теперь все, что записано в $stderr
, в конечном итоге попадет в файл журнала. Форматирование, однако, будет немного странным. Каждый раз, когда любой из методов записи вызывает #write
, в лог-файл будет добавлена новая запись. Например, #puts
, вызываемый с помощью массива, будет вызывать #write
для каждой записи массива, и снова с символом новой строки между каждой записью, что приведет к 2n - 1 записям журнала, n - 1 из которых будет пустым.
Вы можете сделать переопределенный метод #write
более сложным, чтобы справиться с этим, возможно, используя внутренний буфер, и вызывать регистратор только тогда, когда считаете, что у вас есть полное сообщение. В качестве альтернативы вы можете переопределить отдельные методы для записи в сам логгер. Если вы это сделаете, класс IOToLog
не обязательно будет наследоваться от IO
.
Ваше лучшее решение будет зависеть от того, как вы хотите, чтобы стандартный вывод ошибок отображался в лог-файле, как ваша программа использует $stderr
, и сколько работы вы хотите выполнить, реализуя методы из IO
.