Я работаю над библиотекой Ruby, которая должна выполнять журналирование. В идеале я хотел бы, чтобы несколько рабочих процессов могли входить в один файл. Если посмотреть на источник класса Logger
из стандартной библиотеки Ruby, я вижу, что прилагаются усилия для синхронизации записи в журнал из нескольких потоков (как указано в ответе Является ли Ruby's stdlib класс Logger с потоком-безопасностью?).
Кажется, существует аналогичная проблема, когда несколько процессов записывают в один и тот же файл журнала: в зависимости от того, как лежащие в основе слои решают блокировать/разделять записи, каждое сообщение журнала может не поддерживать его целостность.
Итак, существует ли способ использования стандартного класса Logger
, позволяющего нескольким процессам безопасно регистрироваться в одном файле? Если нет, как это обычно выполняется в проектах Ruby?
Вот что я подразумеваю под "безопасно":
- Каждая строка журнала "атомарная" - появляется полностью, без прерывания до начала следующего сообщения. например ничего как
[1/1/2013 00:00:00] (PID N) LOGMESS[1/1/2013 00:00:01] (PID M) LOGMESSAGE2\nAGE1
- Журнальные сообщения не обязательно должны строго упорядочиваться между процессами, пока метки времени, отображаемые в журнале, верны.
Обновление
Я решил взять совет оловянного человека и написать тест, который вы можете найти здесь: https://gist.github.com/4370423
Краткая версия: Winfield корректна, по крайней мере, при использовании Logger
по умолчанию, это безопасно использовать из нескольких процессов одновременно (для определения "безопасный", приведенный выше).
Ключевым фактором является то, что если задан путь к файлу (вместо уже открытого объекта IO), Logger откроет файл с режимом WRONLY|APPEND
и установит sync=true
на нем. Сочетание этих двух вещей (по крайней мере, на моем тестировании в Mac OS X), похоже, позволяет безопасно регистрировать одновременно несколько процессов. Если вы хотите передать уже открытый объект ввода-вывода, просто убедитесь, что вы создали его таким же образом.