Jeśli tworzysz rejestratora siebie, można utworzyć obiekt File
pierwszy, a następnie użyć go do tworzenia rejestratora i przypisać ją do $stderr
:
log_file = File.new('foo.log', 'a')
logger = Logger.new(log_file, 'weekly')
$stderr = log_file #usually no need to use reopen
Zauważ, że to spowoduje wyjście dziennika jest mieszany z wynikiem $stderr
, co może powodować problemy podczas analizowania pliku dziennika, spodziewając się, że ma on określony format (tak samo będzie z twoim rozwiązaniem).
Jeśli nie masz pliku bazowego, ale po prostu odbierasz logger
z innego miejsca, jest to nieco trudniejsze. Potrzebny jest obiekt podobny do IO
, który można przypisać do $stderr
i przekazuje wszystko, co do niego napisał, do rejestratora. Klasa Ruby w wersji IO
jest niestety dość ściśle powiązana z bazowym systemem i/o (deskryptorami plików itp.) I nie ma ogólnego interfejsu, który można wykorzystać do tworzenia strumieni wejściowych i wyjściowych. (StringIO
jest godnym uwagi wyjątkiem).
Jednak większość, jeśli nie wszystkie, z metod wyjściowych IO
ostatecznie przejść #write
, więc nadrzędnymi tę jedną metodę można zbliżyć się do tego, co jesteś po:
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)
Teraz wszystkie zapisywane w $stderr
zakończy się przechodzeniem do pliku dziennika. Formatowanie będzie jednak nieco dziwne. Za każdym razem, gdy któraś z metod zapisu wywoła #write
, w pliku logu pojawi się nowy wpis. Na przykład: #puts
wywołany z tablicą wywoła #write
dla każdego wpisu tablicy, i ponownie znakiem nowej linii między poszczególnymi wpisami, w wyniku czego pojawią się wpisy dziennika 2n - 1, z których n - 1 będzie puste.
Można przesłonić metodę #write
bardziej złożoną, aby sobie z tym poradzić, być może za pomocą wewnętrznego bufora, i wywoływać tylko program rejestrujący, gdy myślisz, że masz pełną wiadomość. Alternatywnie można zastąpić poszczególne metody, aby sami zapisali dane do rejestratora. Jeśli to zrobisz, klasa IOToLog
niekoniecznie będzie musiała dziedziczyć po IO
.
Najlepszym rozwiązaniem będzie zależeć od tego, jak chcesz się standardowe wyjście błędów, aby pojawić się w dzienniku, w jaki sposób program używa $stderr
i jak chcesz robić metod wykonawczych z IO
dużo pracy.
Świetna odpowiedź, dzięki! W moim przypadku tworzę rejestrator, więc twoje pierwsze rozwiązanie jest czyste i eleganckie. Szczególnie podoba mi się, że uwzględniłeś obejście tego drugiego przypadku. (Choć w takim przypadku mógłbym zalecić mój włamanie do osiągnięcia i pobrania pliku bezpośrednio.) – Phrogz
Druga metoda nie działa dla mnie na jruby. Pojawia się następujący błąd: (Errno :: EBADF) Niepoprawny deskryptor pliku –
Powinien być '@ logger.error (ciąg)' Myślę, że – lojza