В случае не CRITICALERROR | CRASH, где ожидалось, что приложение продолжит работу после вызова журналирования, было бы лучше поставить в очередь (потокобезопасную очередь производителя-потребителя) от каждой структуры журнала до потока журналирования, который выполняет запрошенные действия. Поток журналирования обычно освобождает структуры после обработки. Некоторые преимущества:
1) Действие, предпринимаемое для каждого запроса регистрации, сводится к неправильному использованию структуры, ее загрузке и помещению в очередь. Если диск временно занят, или имеет большую задержку, потому что он находится в сети, или становится фактически недоступным, вызывающий поток (ы) продолжит работать почти нормально. При этом набор приложений, которые не будут работать только потому, что включено ведение журнала, уменьшается. Пользователь с какой-то периодически возникающей проблемой, которую вы не можете воспроизвести, может быть проинструктирован включить регистратор с небольшой вероятностью, что регистрация повлияет на нормальные операции или, что еще хуже, приведет к задержкам, которые скрывают ошибку.
2) По тем же причинам, что и (1), добавление / изменение функциональности регистратора даже во время выполнения намного проще. Например, может быть, вы хотите ограничить размер файлов журнала или создавать новый файл журнала с указанием даты / времени каждый день. «Нормальный» вызов привел бы к длительной задержке в вызывающем потоке, когда старый файл был закрыт, а новый открыт. Если ведение журнала отключено, все, что вы получаете, - это временное увеличение числа структур журнала в очереди.
3) Управление регистрацией стало проще. В приложении с графическим интерфейсом регистратор может иметь свою собственную форму, в которой параметры журнала могут быть изменены. У вас может быть кнопка «Создать файл журнала сейчас», которая при щелчке помещает в очередь структуру «LOGCONTROL» для потока журнала вместе со всеми другими сообщениями журнала. Когда поток получает его, он открывает новый файл журнала.
4) Пересылка сообщений журнала довольно проста. Может быть, вы хотите просмотреть зарегистрированные сообщения, а также записать их на диск - поставьте в очередь структуру 'LOGCONTROL', которая указывает потоку сохранить функцию ptr, переданную в структуре, и впредь вызывать эту функцию с последующими сообщениями регистрации после записи их в диск. Переданная функция может поставить в очередь сообщения в ваш графический интерфейс для отображения в окне типа «терминал» (PostMessage в Windows, Qt и т. Д. Имеют аналогичные функции, позволяющие передавать данные в графический интерфейс). Конечно, в *** x вы могли бы открыть окно консоли и «tail-f» файл журнала, но это не будет казаться особенно элегантным для пользователя GUI, более сложным в управлении для пользователей и в любом случае недоступно в стандартной комплектации в Windows (сколько пользователей знают, как скопировать вставку из окна консоли и отправить вам сообщение об ошибке по электронной почте?).
Другая возможность состоит в том, что поток регистрации может быть проинструктирован для потоковой передачи текста журнала на удаленный сервер - другая структура 'LOGCONTROL' может передавать имя хоста / порт потоку регистратора. Временные задержки открытия сетевого подключения к серверу не будут иметь значения из-за сообщений в очереди.
5) «Ленивая запись» и другие подобные улучшения производительности становятся проще, но:
Недостатки:
1) Основным из них является то, что, когда вызов журнала возвращается запросчику, операция журнала, вероятно, еще не произошла. Это очень плохие новости в случае с CRITICALERROR | CRASH, и может быть неприемлемым в некоторых случаях даже при «обычной» регистрации сообщений о ходе выполнения и т. Д. В этих случаях должна быть возможность обойти и сделать прямую запись / очистку диска - fOpen / CreateFile - отдельный «Direct.log», добавить, написать, очистить, закрыть. Медленно, но безопасно, на случай, если приложение взорвется после возврата из журнала.
2) Более сложный, поэтому больше разработки, больше условий, больший интерфейс API включают.
Rgds,
Martin