Студент
56 / 56 / 38
Регистрация: 17.09.2012
Сообщений: 292
Записей в блоге: 2
1

Реализация журнала ошибок и протоколирования событий

04.09.2015, 15:34. Показов 5087. Ответов 14
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день, уважаемое сообщество.
При написании выпускной работы появилась необходимость вести журнал ошибок работы программы, и протоколирования событий программы. События и ошибки могут быть самые разные (в теории), т.к. в программе обрабатываются прерывания с платы, работа с сетью и просто, ошибки вычислений.
Подскажите в какую сторону стоит копать, может я не то гуглю и не могу наткнуться на нужное.

P.S. Разработка ведется в Embarcadero RAD Studio 8.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
04.09.2015, 15:34
Ответы с готовыми решениями:

Парсинг журнала событий
возникла задача, получить некоторые данные из event log'a Windows, как это все реализовать ? с...

DLL для Журнала Событий Windows
кто-нибудь знает подходящую DLL с пустым сообщением? Например "%s" чтобы было тупо. Очень нужна...

Реализация событий в С++
Мне нужно реализовать события, как в Дельфи или С++ Builder, на Visual C++. Но стандартный С++ не...

Тетрис - Реализация таймера и обработка событий с клавиатуры
Пишу консольный тетрис. Столкнулся с проблемой таймера и перехвата событий с клавиатуры. Раньше с...

14
7784 / 6553 / 2982
Регистрация: 14.04.2014
Сообщений: 28,615
04.09.2015, 16:25 2
В чём сложность? Открой текстовый файл и записывай в него.
0
Студент
56 / 56 / 38
Регистрация: 17.09.2012
Сообщений: 292
Записей в блоге: 2
04.09.2015, 17:11  [ТС] 3
Цитата Сообщение от nmcf Посмотреть сообщение
В чём сложность? Открой текстовый файл и записывай в него.
Каким образом обрабатывать ошибки и вести протокол?
Выделил я фрагмент в коде который может вызвать ошибку при работе с try, catch, а дальше что?
+ это должно формировать более-менее читаемый отчет (возможно потребуется распечатка определенного момента работы программы)
0
7784 / 6553 / 2982
Регистрация: 14.04.2014
Сообщений: 28,615
04.09.2015, 17:13 4
Ну как что? Нашёл ошибку - сделал запись. Какую-нибудь функцию предусмотри, которую можно в любом месте программы вызвать для записи в журнал.
1
6045 / 2160 / 753
Регистрация: 10.12.2010
Сообщений: 6,005
Записей в блоге: 3
04.09.2015, 17:47 5
Цитата Сообщение от _include Посмотреть сообщение
Каким образом обрабатывать ошибки и вести протокол?
Как обрабатывать ошибки в коде, это уже вопрос к программе. Протоколы же нужно вести таким образом, чтобы при его прочтении было ясно состояние программы в каждый отмеченный момент времени. Ну то есть: логгируете вход в функцию, входные параметры в читаемом виде, если возможно, логгируете критичные участки (критичные ветвления, флаги, и т.п.), логгируете выход из функции, возвращаемое значение. В таком духе в качестве первого приближения пойдет. Если интересно в про-форме как делать надо, то милости просим в группу стандартов ISO/IEC JTC 1/SC 7, для начала пойдет вам ISO/IEC 11411:1995

Добавлено через 10 минут
Кстати, тут неплохо определиться: вам протокол исполнения вести надо, или трейс? То, что я описал -- это трейс. А протокол исполнения отображает только основные события и данные в цепочке логики исполнения.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
04.09.2015, 19:50 6
Лучший ответ Сообщение было отмечено _include как решение

Решение

Цитата Сообщение от _include Посмотреть сообщение
При написании выпускной работы появилась необходимость вести журнал ошибок работы программы, и протоколирования событий программы. События и ошибки могут быть самые разные (в теории), т.к. в программе обрабатываются прерывания с платы, работа с сетью и просто, ошибки вычислений.
Подскажите в какую сторону стоит копать, может я не то гуглю и не могу наткнуться на нужное.
по поводу коммуникации:

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

слушающие процессы сливают инфу в базу данных.

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

по поводу содержимого самих данных:

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

по поводу дизайна в исходном коде:

можно конечно навернуть трассер:
механизм, который в автомате пасет трассу функций.

можно тупо руками вставлять вызов функции отправки данных в канал.

трассер - удобная штука.
но здесь нужно понимать:
если что-то случилось, приложение уже находится в нестабильном состоянии.

любые операции, такие, как например - выделение памяти смерти подобны.

то есть, такой трассер он..
просто возможно умрет прежде, чем доставит данные в красивом виде.

изготовление его не то, что бы сложное,
но интересное.

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

слишком уж такая технология тяжело поддерживается.

проще ручками по критичным местам раскидать вызовы логгера.
1
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
04.09.2015, 21:08 7
Цитата Сообщение от _include Посмотреть сообщение
Подскажите в какую сторону стоит копать
Вбиваем в поиск Гугл строку "C++ log library" и получаем тучу интересных результатов:
log4c, log4cpp, Boost.Log, Pantheios, spdlog, easylogging, log4plus, g2log и т.д.

Цитата Сообщение от hoggy Посмотреть сообщение
лично я пришел к выводу, что технология с трассером,
даже при наличии базы данных, с удобной читалкой лога,
в которой можно быстро лопатить стек вызовов и найти причину краша...
слишком уж такая технология тяжело поддерживается.
Наверное, это зависит от самой технологии. Я некоторое время назад стал повсеместно
использовать Windows Software Tracing (WPP) в тонкой обертке из пары-тройки функций и
макросов, оказалось очень даже удобно, эффективно и дешево. Некоторые достаточно
тонкие и сложные ошибки ну никогда бы не выловили, если бы не хорошая трассировка.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
04.09.2015, 21:12 8
Цитата Сообщение от Убежденный Посмотреть сообщение
log4c, log4cpp, Boost.Log, Pantheios, spdlog, easylogging, log4plus, g2log и т.д.
log4c, log4cpp, Boost.Log, easylogging, log4plus - шлак. остальные не пользовал.

Цитата Сообщение от Убежденный Посмотреть сообщение
использовать Windows Software Tracing (WPP) в тонкой обертке из пары-тройки функций и
макросов, оказалось очень даже удобно, эффективно и дешево.
это звучит интересно.
вы могли бы рассказать поподробнее.

так то я кросс-платформенный программист.
я смотрел в сторону поддержки "отладочных процессов" в разных осях.
и понял, что кросс-платформа здесь слишком экономически не выгодная,
что бы ввязываться в такую авантрюру.
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
04.09.2015, 23:52 9
Лучший ответ Сообщение было отмечено _include как решение

Решение

Цитата Сообщение от hoggy Посмотреть сообщение
это звучит интересно. вы могли бы рассказать поподробнее.
WPP не похож на большинство логгеров, с которыми мне приходилось работать.

В WPP данные пишутся не в файл, а в специальные буферы, предоставленные системой.
Эти буферы удерживаются системой до самого конца сеанса трассировки, даже если
приложение, которое туда писало, уже завершилось (возможно, аварийно). Запись в
буфер, разумеется, очень быстрая, с файлом или с каким-нибудь DbgPrint или
OutputDebugString даже сравнивать не стоит - обойдет на несколько порядков.
Отдельный процесс или компонент может в фоне вычитывать содержимое буферов и
писать их в форматированном виде туда, куда ему хочется - файл, консоль,
сокет и так далее.

Все заботы о синхронизации потоков, сбрасывании буферов на диск и многом другом
система берет на себя.

WPP начинается еще до этапа компиляции. Исходники обрабатываются специальным
препроцессором, который генерирует заголовок с необходимыми макросами и функциями.
Каждый файл, где используется WPP, должен подключить сгенерированный для него
заголовок. В результате подключения такого заголовка и в зависимости от опций
WPP-препроцессинга, функция логирования превращается в некоторую конструкцию кода,
который выполняет всю необходимую работу. Сами исходники, естественно, не трогаются.

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

Интересно, что в результате препроцессинга форматная строка (не знаю, как
правильно назвать) превращается в некий ID. То есть, вот такой, например, вызов:
C
1
WppLog("Connecting to server %s...", pHostName);
на самом деле развернется в нечто такое:
C
1
WppLog(SomeID, pHostName);
На этапе препроцессинга WPP сохраняет форматную строку и другую информацию.
Когда нужно будет получить логи в удобочитаемом виде, эта информация будет
использована в обратном направлении - ID превратится в строку текста с
подставленными аргументами.

Получается экономия: текст форматной строки не хранится ни в самой программе,
ни в буферах трассировки, ID писать в буферы немного быстрее, чем текст.
Еще один приятный побочный эффект - если вы случайно передадите неправильное
количество аргументов в лог-функцию, WPP-препроцессор смачно выругается и в
итоге не даст скомпилировать проект.

Собранные WPP-препроцессором данные можно хранить либо в PDB-файлах вместе с
отладочной информацией, либо в отдельных TMF-файлах. Из PDB можно в любой момент
получить TMF. Плюс TMF в том, что его можно спокойно отдать клиенту, так как
никакой полезной для реверса информации он не содержит, в отличие от PDB.

Типичный "жизненный цикл" WPP выглядит примерно так. Допустим, у клиента обнаружилась
некая проблема с вашим софтом. Запускается сеанс трассировки (программно или с
помощью внешних утилит - не суть). Доступен один из трех режимов:

1. real-time session. Данные, которые пишутся приложениями в WPP-буферы, сразу же
форматируются и сохраняются, например, на диск в текстовом виде, или в консоль,
или туда и туда.

2. log session. Данные пишутся в "сыром" виде в файл. После остановки сеанса
трассировки их нужно вручную отформатировать в удобочитаемый вид.

3. boot session (GlobalLogger (XP+) / Auto-Logger (Vista+)).
Предназначен для логирования событий на ранних стадиях загрузки Windows.
Обычно полезно для диагностики ошибок в драйверах, службах и т.п.

После воспроизведения ошибки сеанс трассировки останавливается, собираются логи.
Потом выполняется их форматирование, на этом этапе потребуются PDB- или TMF-файлы.
Ну и все, можно читать логи и чесать в затылке. Для real-time можно использовать
вывод в консоль или штатный Viewer с GUI-интерфейсом (TraceView).

Степень детализации, информативность и т.п. - все это настраивается.
WPP автоматически собирает следующие данные:

время события (точность настраивается);
название исходного файла, функции и строки кода;
номер CPU, на котором выполнялся поток в момент записи;
PID процесса / TID потока;
level / flags (info, warning, error, trace и т.п.);
...

Во время запуска сеанса трассировки можно указать, например, чтобы в буфер писались
только события warning и error. Есть типичные для логгеров опции вроде ротации логов,
размеров буферов, flush timeout и т.д.

Параметры Level, Flags и некоторые другие можно полностью кастомизировать и
заставить WPP работать по своим правилам, отличных от всяких стандартов.

Работа в режиме ядра тоже поддерживается.

--------

Теперь о минусах, без этого повесть была бы не полной и не честной.

WPP - инструмент, безусловно, хороший, но местами сыроватый:

* Чтобы интегрировать WPP в свой проект, придется поковыряться с командной строкой,
консольными утилитами и конфигурационными файлами. Решения в стиле "one click" нет.

* Некоторые опции могут не заработать, пока не переставишь их местами.

* Ошибки, которые выдает препроцессор, очень часто бывают совершенно невнятными.

* Не совместимо с опцией "Program Database for Edit & Continue" (Visual C++).

* При добавлении в проект очередного исходного файла придется выполнять
один и тот же "ритуал": добавить этот исходник под контроль WPP-препроцессора и
включить в него нужный заголовок.

* На системах до Windows Vista есть некоторые проблемы, например могут
потеряться некоторые сообщения при высокой интенсивности логирования
(когда их много тысяч в секунду).

* При вызове функции логирования теряется код GetLastError.
Обычно это не проблема, но если этот код нужно сохранить, придется либо писать так:
C
1
2
DWORD const GLE = GetLastError();
WppLog("AdjustTokenPrivileges failed (GLE = 0x%.8lx).", GLE);
либо прикручивать в функцию логирования дополнительные инструкции.

* возможно, я просто не разобрался, но мне не удалось заставить WPP-препроцессор
нормально работать с функциями и классами, описанными в заголовках.

* поддержка гарантируется только для Visual C++, как WPP себя ведет на
других компиляторах - не определено.

--------

Резюме.

Я считаю, что выгоды использования WPP и относительная простота его интеграции весят
значительно больше, чем приведенные минусы. У меня был такой, например, баг: прокси-сервер
на асинхронных сокетах (IOCP) иногда начинал подвисать, если в браузере сразу открыть
много вкладок с HTTPS-страницами. Подвисал минут этак на 5-7. Как только включались логи
(какая-то типичная плюсовая либа, пишущая данные в файл в стиле printf), нарушались тайминги и
ошибка наглухо переставала воспроизводиться. Три недели (!) я с этим багом бился и ничего не
смог найти, ни в отладчике, ни еще где. Никак. Но WPP помог. В основном за счет того, что
во включенном состоянии оказывал минимальное воздействие на перфоманс и не создавал
побочных эффектов, а еще за счет того, что можно понапихать сообщений с кучей параметров
через каждую строчку кода и не бояться, что оно все начнет "педалить".

Сейчас на работе типичная ситуация: работаешь над каким-нибудь неинтерактивным системным
компонентом (драйвер, служба, система аутентификации и т.п.), там все на ранних стадиях
загрузки Windows, а еще dll, которые загружены в каждый процесс... Где-нибудь что-нибудь
падает или виснет и все, только логи и спасают.

Для того, чтобы не повторять каждый раз одни и те же "заклинания", я себе сделал два
файла - .h и .cpp (для драйверов - .h и .c), которые достаточно подключить к проекту и
прописать несколько опций, чтобы обеспечить поддержку WPP и работу макросов DIAG_INFO,
DIAG_WARN и DIAG_ERR. В отладочной сборке эти макросы превращаются в вызовы функции
OutputDebugString (DbgPrint для драйверов), которые пишут инфу в отладчик, а в релизной - в
вызовы функций трассировки WPP.

Форматирование примерно такое (все настраивается):

Код
...

234 AppManager 2015.08.07-14:44:58.127 PID=0a24 TID=037c CPU=0001
[ERROR] FileStream::open: CreateFileW failed with last error 0x00000002
    Name = "C:\ProgramData\AppManager\settings.json"

235 AppManager 2015.08.07-14:45:01.132 PID=0a24 TID=0440 CPU=0000
[INFO] OnOpenSession: Connecting to the host:
    Addr    = 192.168.0.106:49158
    Mode    = Checkout
    Timeout = 5s
    Arg     = "get-realm-sha1"

236 AppManager 2015.08.07-14:45:01.155 PID=0a24 TID=0440 CPU=0000
[INFO] OnOpenSession: Update event signaled (type = global, from PID = 0x944).

...
Если вывод идет в отладчик, верхняя строчка каждого сообщения обрезается
(т.к. при отладке она обычно не нужна).

Вся необходимая информация про WPP находится здесь и далее по ссылкам:

WPP Software Tracing
https://msdn.microsoft.com/en-... s.85).aspx

Вот еще любопытная статейка о том, как на базе WPP можно "дом построить":

EventTrace for Windows. Высокоскоростная передача отладочных сообщений драйвера по сети
http://habrahabr.ru/post/156817/
8
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
05.09.2015, 00:35 10
супер.

не кроссплатформенно, но идея классная.

колоссальное спасибо.

Добавлено через 17 минут
у меня выдает: нельзя дважды поблагодарить

прошу администрацию дать + господину Убежденный максимум,
на что способна моя регистрация, как лучший ответ в теме.

я нахожу развертнутый ответ крайне полезным.
а его сожержание тянет на целую статью.

добавил в копилку своих знаний.
1
232 / 135 / 19
Регистрация: 10.11.2015
Сообщений: 305
21.03.2017, 12:48 11
Цитата Сообщение от Убежденный Посмотреть сообщение
Для того, чтобы не повторять каждый раз одни и те же "заклинания", я себе сделал два
файла - .h и .cpp (для драйверов - .h и .c), которые достаточно подключить к проекту и
прописать несколько опций, чтобы обеспечить поддержку WPP
А можно поподробней? Как ты это сделал? Пытаюсь использовать WPP в Visual Studio Professional 2008. Делаю примерно так, но данный подход не совсем удобен.
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
21.03.2017, 14:26 12
Мой подход принципиально ничем не отличается.
Только я не создаю новый проект, а прописываю запуск WPP-препроцессора в Pre-Build Events.
А настройки функции трассировки прописываются в отдельном заголовке.
Инструкциями begin_wpp config, USEPREFIX, FUNC, USESUFFIX, end_wpp и т.д.
2
232 / 135 / 19
Регистрация: 10.11.2015
Сообщений: 305
21.03.2017, 15:26 13
Убежденный, но ведь Pre-Build Events, в отличии от Custom Build Rules, нельзя настроить, чтобы запуск был только для измененных *.cpp. И тебе все равно приходится *.tmh файлы в каждый модуль подключать? Видимо у тебя в Pre-Build Events путь к какой-то промежуточной утилите, а не сразу к tracewpp.exe. Нет?

И да.

Цитата Сообщение от Убежденный Посмотреть сообщение
я себе сделал два
файла - .h и .cpp (для драйверов - .h и .c), которые достаточно подключить к проекту
Что у тебя в cpp файле?
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
21.03.2017, 15:33 14
Цитата Сообщение от jupman Посмотреть сообщение
но ведь Pre-Build Events, в отличии от Custom Build Rules, нельзя настроить, чтобы запуск был только для измененных *.cpp.
Возможно. Но я в такие детали не вникал, меня пока устраивает, как оно работает.

Цитата Сообщение от jupman Посмотреть сообщение
И тебе все равно приходится *.tmh файлы в каждый модуль подключать?
Да. У меня в начале каждого исходника написано примерно следующее:
C
1
2
3
#if defined (DIAG_MODE_WPP)
#include "MyModule.tmh"
#endif
Цитата Сообщение от jupman Посмотреть сообщение
Видимо у тебя в Pre-Build Events путь к какой-то промежуточной утилите, а не сразу к tracewpp.exe. Нет?
У меня там bat-файл, который все разруливает

Цитата Сообщение от jupman Посмотреть сообщение
Что у тебя в cpp файле?
Там реализация функций-оберток DIAG_INITIALIZE и DIAG_SHUTDOWN.
В debug-конфигурации они ничего не делают. В release вызывают
WPP_INIT_TRACING и WPP_CLEANUP соответственно.
2
232 / 135 / 19
Регистрация: 10.11.2015
Сообщений: 305
04.06.2017, 09:30 15
Цитата Сообщение от Убежденный Посмотреть сообщение
возможно, я просто не разобрался, но мне не удалось заставить WPP-препроцессор
нормально работать с функциями и классами, описанными в заголовках.
Возможно ты уже разобрался, но отпишу свое решение:

1) Для того что бы tracewpp.exe не игнорировал hpp-файлы есть параметр ext. Плюс preserveext (включить расширение в имя tmh-файла) что бы избежать конфликта имен. Данные параметры могут не работать в зависимости от расположения в командной строке. У меня они работают когда стоят в начале, сразу после tracewpp.exe.
tracewpp.exe -ext:.cpp.hpp -preserveext:.cpp.hpp ...
2) Если посмотреть на код генерируемый WPP, видно, что предыдущие макросы переопределяются. Т.о. после подключение tmh-файла должно быть использование макросов из него, только затем новое подключение tmh-файла. Я взял за правило подключать tmh-файл после любых директив include.
2
04.06.2017, 09:30
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
04.06.2017, 09:30
Помогаю со студенческими работами здесь

Реализация программы на С++ (Найти вероятности следующих событий:)
Помогите пожалуйста реализовать на С++ или на С# программу по этой задаче N стрелков...

Реализация простейшего чата: как избежать ошибок?
Я пишу штото типа чата, написал - шду ответа, но на одном компе запущу один клиент, роботает норм,...

Нужен батник для создания отчета событий и их свойств из журнала событий на локальном компьютере
Пакетный файл, предназначенный для создания отчета событий и их свойств из журнала событий на...

Обработка журнала событий
Добрый день! Помогите написать скрипт на VBS, сам то вот только первый раз столкнулся с VBS....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru