Вот сценарий. У вас есть большое количество устаревших сценариев, и все они используют общую библиотеку. Указанные сценарии используют оператор print для диагностического вывода. Никакие изменения не допускаются в сценариях - они распространяются повсеместно, имеют свои одобрения и уже давно оставили плодотворные долины надзора и контроля.
Теперь пришла новая потребность: регистрация должна быть добавлена в библиотеку. Это должно быть сделано автоматически и прозрачно, без необходимости изменения скриптов пользователями стандартной библиотеки. К обычным библиотечным методам можно просто добавить журналы вызовов; это легкая часть. Сложность заключается в том, что диагностический вывод этих сценариев всегда отображался с использованием оператора print. Этот диагностический вывод должен быть сохранен, но, что не менее важно, обработан.
В качестве примера такой обработки библиотека должна записывать только напечатанные строки, содержащие слова «предупреждение», «ошибка», «уведомление» или «внимание». Приведенный ниже чрезвычайно простой и хитрый пример кода (tm) будет записывать некоторые из указанных выходных данных:
sub CheckPrintOutput
{
my @output = @_; # args passed to print eventually find their way here.
foreach my $value (@output) {
Log->log($value) if $value =~ /warning|error|notice|attention/i;
}
}
(Я бы хотел избежать таких проблем, как «что на самом деле должно быть зарегистрировано», «печать не должна использоваться для диагностики», «perl sucks» или «в этом примере есть недостатки xy и z» ..) это очень упрощено для краткости и ясности.)
Основная проблема сводится к захвату и обработке данных, переданных на печать (или любой другой встроенный perl, согласно этим рассуждениям). Является ли это возможным? Есть ли способ сделать это чисто? Существуют ли какие-либо модули журналирования, которые имеют зацепки, чтобы позволить вам это сделать? Или этого следует избегать, как чумы, и я должен отказаться от того, чтобы когда-либо захватывать и обрабатывать печатную продукцию?
Дополнительно: это должно работать кроссплатформенно - windows и * nix одинаково. Процесс запуска сценариев должен оставаться таким же, как и вывод из сценария.
Дополнительный дополнительный: интересное предложение, сделанное в комментариях ответа codelogic:
Вы можете создать подкласс http://perldoc.perl.org/IO/Handle.html и создать свой
собственный дескриптор файла, который будет выполнять регистрацию. - Камил Кисиэль
Это может быть сделано с двумя оговорками:
1) Мне нужен был бы способ экспортировать эту функциональность любому, кто использует общую библиотеку. Это должно было бы автоматически применяться к STDOUT и, возможно, к STDERR.
2) Документация IO :: Handle гласит, что вы не можете сделать это подклассом, и мои попытки до сих пор были бесплодными. Есть ли что-то особенное, что нужно для создания подклассов IO :: Handle? Стандартный «use base» IO :: Handle, а затем переопределение методов new / print, похоже, ничего не делают.
Окончательное редактирование: похоже, IO :: Handle - тупик, но Tie :: Handle может это сделать. Спасибо за все предложения; они все действительно хороши. Я собираюсь попробовать маршрут Tie :: Handle. Если это вызовет проблемы, я вернусь!
Добавление: обратите внимание, что после небольшой работы с этим я обнаружил, что Tie :: Handle будет работать, если вы не сделаете ничего хитрого. Если вы используете какие-либо функции IO :: Handle с вашими связанными STDOUT или STDERR, по сути, это просто дрянь, чтобы они работали надежно - я не смог найти способ заставить метод autoflush IO :: Handle работать с моими связанными справиться. Если бы я включил автозапуск до того, как связал ручку, это сработало бы. Если это работает для вас, маршрут Tie :: Handle может быть приемлемым.