Особенности проектирования для журнала ошибок / библиотеки уведомлений в C - PullRequest
2 голосов
/ 03 июня 2011

Сейчас я работаю над несколькими программами и разочаровался в некоторых случайных способах отладки своих программ и регистрации ошибок.Поэтому я решил занять пару дней, чтобы написать библиотеку ошибок, которую я смогу использовать во всех моих программах.Я делаю большую часть своей разработки в Windows, широко используя Windows API, но ключевым здесь является гибкость: в идеале эта библиотека должна оставаться гибкой, предлагая опции уведомлений программиста в консольных приложениях и приложениях с графическим интерфейсом в Windows и Unix-подобных средах.

Моя первоначальная идея состоит в том, чтобы использовать одну библиотеку, которая использует условное включение препроцессора заголовков для Windows и Unix в зависимости от текущей среды.Например, в приложении win32 уведомление об ошибке консоли (пока возможно) не требуется;вместо этого простейший

MessageBoxA/W(hWndParent, TEXT("Some error message that makes sense in context"), TEXT("Application Name"), MB_ICONERROR | MB_OK)

имеет смысл.С другой стороны, в Linux все немного сложнее:

GtkWindow *w;
w = gtk_message_dialog_new(pOwner, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, TEXT("Some error message");
gtk_window_set_title(w, TEXT("Application Name"));

В любой из этих операций также может быть полезна простая регистрация файлов с дополнительной информацией об ошибке (функция, файл, строка и т. Д.).в точном определении источника и отслеживании потока.

Более того, регистрация должна быть возможной: даже когда вызывается функция, требующая регистрации ошибок / уведомления, должна быть возможность показать последовательность вызовов функций в программе, еслиэтот уровень ведения журнала активирован.

Таким образом, мои первоначальные соображения состоят в том, чтобы иметь библиотеку, которая включает все эти функции, с минимальными издержками благодаря условным условиям препроцессора.Я думаю, что было бы разумнее разбить это на пару структур:

  • Структура "main", которая передается каждой функции в основной программе, требующей регистрации, и содержит
    • Битовая маска, содержащая коды состояния, для которых необходима регистрация файлов (например, NOERROR | WARNING | CRITICALERROR или CRITICALERROR | CRASH)
    • Указатель на структуру "output"
    • Связансписок узлов "информации об ошибках"
  • Структура "output", которая обрабатывает печать в файл, отображение окон сообщений и печать на консоль
  • Информация об ошибке"struct, которая содержит информацию об ошибке (функция, файл, строка, сообщение, тип и т. д.)

Это только мои первоначальные мысли об этой библиотеке.Кто-нибудь из вас может вспомнить какую-либо информацию, которую я должен включить?Еще одна важная проблема для меня - атомарность добавления ошибок: вероятно, что другой поток может создать ошибку, а не тот, который регистрирует ошибку, поэтому я должен убедиться, что создание и добавление узла ошибки на самом деле является атомарной операцией.Таким образом, мьютексы, скорее всего, были бы тем же способом, что и при синхронизации.

Спасибо за помощь!

Ответы [ 2 ]

1 голос
/ 03 июня 2011

В случае не 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

0 голосов
/ 04 июня 2011

Привет, я использую это для другого языка, но вы можете исследовать его и следовать его дизайну http://www.gurock.com/smartinspect/

привет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...