Si va a crear el registrador usted mismo, puede crear el objeto File
primero, y luego utilizarlo para crear el registrador y asignarlo a $stderr
:
log_file = File.new('foo.log', 'a')
logger = Logger.new(log_file, 'weekly')
$stderr = log_file #usually no need to use reopen
Tenga en cuenta que esto se traducirá en la salida del registro confundirse con la salida $stderr
, lo que puede causar problemas si analiza el archivo de registro esperando que esté en un formato determinado (esto también sucederá con su solución).
Si no tiene el archivo subyacente pero acaba de recibir el logger
desde otro lugar, es un poco más complicado. Lo que se necesita es un objeto similar IO
que se puede asignar a $stderr
y pasa todo lo que está escrito en el registrador. La clase IO
en Ruby lamentablemente está muy relacionada con el sistema de E/S subyacente (descriptores de archivos y similares), y no hay una interfaz general que se pueda usar para crear flujos de entrada y salida. (StringIO
siendo la excepción notable).
Sin embargo la mayoría, si no todos, de los métodos de salida en última instancia IO
pasar por #write
, por lo que esta reemplazando un método que puede acercarse a lo que está buscando:
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)
Ahora nada escrito $stderr
terminará yendo al archivo de registro. Sin embargo, el formateo será un poco extraño. Cada vez que cualquiera de los métodos de escritura llame al #write
, se hará una nueva entrada en el archivo de registro. Por ejemplo, #puts
llamado con una matriz llamará a #write
para cada entrada de la matriz, y nuevamente con un carácter de nueva línea entre cada entrada, lo que resulta en 2n - 1 entradas de registro, n - 1 de las cuales estará en blanco.
Puede hacer que el método Oreemplazado sea más complejo para manejar esto, quizás usando un búfer interno, y solo llame al registrador cuando crea que tiene un mensaje completo. Alternativamente, usted puede anular los métodos individuales para escribir en el registrador. Si hiciera esto, la clase IOToLog
no necesariamente tendría que heredar de IO
.
Su mejor solución dependerá de cómo quiera que aparezca la salida de error estándar en el archivo de registro, cómo su programa usa $stderr
, y la cantidad de trabajo que desea hacer implementando métodos desde IO
.
¡Gran respuesta, gracias! En mi caso, estoy creando el registrador para que su primera solución sea limpia y elegante. Me gusta especialmente que haya incluido la solución para el otro caso. (Aunque en tal caso podría abogar mi intento de acercarme y tomar el archivo directamente.) – Phrogz
El segundo método no funciona para mí en jruby. Me sale el siguiente error: (Errno :: EBADF) Descriptor de archivo incorrecto –
Debería haber '@ logger.error (string)' Creo – lojza