6 января 2010 г.

Советы и трюки в EurekaLog, часть 1

Многие наши клиенты часто спрашивают, как сделать различные вещи с EurekaLog. Ну, у нас есть документация (chm-файл, а также online), которая описывает опубликованный интерфейс (функции и т.п.), который вы можете использовать для смены поведения по-умолчанию. Это документация в "стиле словаря". Чтобы использовать её, вам нужно изучить все кусочки и придумать способ, как сложить их вместе, чтобы получить интересное/нужное поведение. Кажется, что это слишком много работы для типичного человека, потому что все продолжают задавать простейшие вопросы типа "Моё приложение работает в окружении без оператора. Как я могу отключить диалог об ошибке EurekaLog?".

Поэтому, я запланировал серию постов о типичных сценариях использования и их реализации. Это будут статьи типа Q&A/FAQ. Т.е. простые вопросы и ответы на них. Ответы обычно будут включать в себя манипуляцию настройками или написание небольших кусочков кода (как правило - обработчиков событий). Итак, часть первая.

Q: Как я могу определить, активна ли EurekaLog?

A: Мы рекомендуем использовать проверки IFDEF, например:
{$IFDEF EUREKALOG}
uses
  ExceptionLog;
{$ENDIF}

{$IFDEF EUREKALOG}
  CurrentEurekaLogOptions ...
{$ENDIF}
Или же вы можете использовать эти функции (в модуле ExceptionLog)
function IsEurekaLogActive: Boolean;
function IsEurekaLogActiveInThread(ThreadID: DWord): Boolean;
function IsEurekaLogInstalled: Boolean;
Но использование функций будет означать внедрение кода EurekaLog в ваше приложение, даже если EurekaLog была отключена.
Описание функций вы можете найти в документации (http://www.eurekalog.com/help/eurekalog/).

Заметьте, что есть разница между "проект был скомпилирован без EurekaLog" и "в проекте есть EurekaLog, но она не активна".

Q: Как я могу отправлять отчёт автоматически, без диалога (который требует вмешательство оператора)?

A: Есть как минимум три способа это сделать.

1. Установить "Dialog type" в "(none)". Эта опция размещается на вкладке "Exceptions dialogs". Этот способ отключит диалог для всех исключений.

Установка Dialog type в none
Вы также можете сделать это в run-time: CurrentEurekaLogOptions.ExceptionDialogType := edtNone (модуля ExceptionLog и ECore).

2. Вы можете использовать фильтры исключений. Добавьте новый фильтр, выберите тип исключения и установите обработчик на EurekaLog, выбрав тип диалога "(none)". Это отключит диалог только для указанного типа исключения. Заметьте, что вы также можете установить обработчик в none или RTL - но отчёт при этом отправлен не будет. См. другие вопросы ниже для примера.

3. Вы можете использовать событие ExceptionActionNotify. Вы можете присвоить свой обработчик, где вы будете смотреть на события типа atShowingExceptionInfo и atShowedExceptionInfo.
Чтобы заблокировать диалог вы устанавливаете Execute := False для atShowingExceptionInfo и Execute := True для atShowedExceptionInfo.
См. также другие примеры.

Если ваше приложении состоит только из одного главного модуля и другой (не ваш) код не использует EurekaLog - то всё, что вам нужно сделать - установить этот обработчик максимально первым действием в вашей программе.

Если же ваше приложение состоит из нескольких DLL - то ответ МОЖЕТ отличаться, смотря как вы их используете.

Q: Я хочу игнорировать определённое исключение. Как я могу это сделать?

A: Зависит от типа этого исключения. Идеальным случаем будет: фильтруемое исключением имеет свой класс. Например, EIdCmdTCPClientConnectError. Т.е. вы хотите игнорировать все исключения типа EIdCmdTCPClientConnectError. Это простейший случай - вы просто используете так называемые фильтры исключений. Идите в опции проекта EurekaLog и откройте вкладку "Exception filters". Включите фильтры (ну, по-умолчанию они включены) и добавьте новый фильтр:

Создание нового фильтра исключений
Введите "EIdCmdTCPClientConnectError" в поле "Class".

Опции ниже определяют, как именно вы хотите изменить поведение по-умолчанию для всех исключений этого типа. Например, чтобы запретить обработку исключения EurekaLog – переключите "Handler" на "RTL". Если вы сделаете это, то каждое исключение EIdCmdTCPClientConnectError будет обрабатываться, как если бы EurekaLog не была установлена (приводя к обычному сообщению об ошибке от VCL/RTL). Вы также можете переключить "Handler" в "none" для полного игнорирования этого исключения (ну, обычно полное игнорирование исключений - это нехорошо, но иногда может пригодиться).

Оставив "Handler" в состоянии "EurekaLog", вы сможет изменить поведение EurekaLog для этого типа исключений. Например, вы можете не отключать создание лога (для диагностики), но не хотите показывать диалог. В этом случае просто переключите "Dialog" в "None".

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

Q: Моё приложение работает в окружении без доступа к Интернету. Я хочу собирать логи вручную в какую-нибудь базу данных. Как мне это сделать?

A: Если вас устроит только лог-файл (без скриншота) - то вы можете просто не заполнять вкладку "Email and Web send" в опциях проекта EurekaLog. Таким способом все исключения будут храниться в едином elf-файле (путь к которому тоже указывается в опциях). Вы можете просто взять его в любой момент и делать с ним, что угодно. Заметим, однако, что поскольку вы храните всю базу данных в едином файле - вы можете захотеть увеличить максимальное кол-во отчётов в этом файле:

Настройки лог-файлов
Q: Но я скорее предпочитаю хранение отчётов и снимков экрана в, скажем, БД MySQL. Как мне это сделать?

A: Просто используйте процедуру SaveScreenshot (или SaveScreenshotToStream) для создания снимка экрана. А ваш отчёт уже тут - по вашему выходному пути.

Q: Как я могу узнать размещение файла с отчётами в run-time?

A: Используйте этот код:
uses
  ExceptionLog, ECore;
...
  LogFileName := ExpandEnvVars(CurrentEurekaLogOptions.OutputLogFile(''));

Q: Куда мне поместить код для сохранения отчёта в мою собственную БД?

A: Вероятно, действие atSavedLogFile в обработчике события ExceptionActionNotify будет неплохим местом.

Q: Я использую сторонний компонент XXX. У меня нет исходных текстов. Иногда компонент возбуждает Access Violation. Это - баг в компоненте. И исправления нет, а компонент очень нужен. Я хотел бы просто игнорировать это конкретное исключение. Это возможно?

A: Конечно, это возможно. Но только, если у вас есть способ отличить это исключение от всех остальных исключений. Например, вы можете посмотреть на адрес возникновения исключения. Если глючный код располагается в DLL – вы можете проверить, принадлежит ли адрес этой DLL. Если компонент располагается в приложении - вы можете проверить, принадлежит ли адрес модулю (unit) компонента. Последнее возможно, если для адреса доступна хоть какая-то отладочная информация. Например:
procedure MyExceptionNofity(EurekaExceptionRecord: TEurekaExceptionRecord; var Handled: Boolean);
var
  Addr: Pointer;
  Module: HINST;
  DebugInfo: TEurekaDebugInfo;
begin
  Addr := EurekaExceptionRecord.ExceptionAddress;

  Module := FindHInstance(Addr);

  Handled := True;
  if AnsiLowerCase(ExtractFileName(GetModuleName(Module))) = 'module.dll' then
    if GetSourceInfoByAddr(Cardinal(Addr), @DebugInfo) then
      Handled := (DebugInfo.ProcedureName <> 'RoutineName');
end;

initialization
  ExceptionNotify := MyExceptionNofity;

Где: 'module.dll' - это имя DLL или exe, в которой лежит ваш компонент. А 'RoutineName' (и, быть может, поле ClassName тоже) идентифицирует проблемный код. Если эта информация не доступна, то вы можете использовать хотя бы UnitName.

Заметьте, что если отладочная информация не доступна для компонента, то вы не сможете получить текстовое описание кода: имена процедур, а иногда и имена модулей. В этом случае неплохим вариантом будет вынос всего глючного кода в отдельную DLL, так что вы смогли бы проверять только имена модулей.

Конечно же, в самом крайнем случае, у вас всегда есть проверка "в лоб", например:
Execute := (EurekaExceptionRecord.ExceptionAddress <> $12345678);

Где: $12345678 - адрес вашего исключения (например, в случае Access Violation этот адрес указан в части сообщения "at address 12345678").

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

Q: Как я могу локализовать сообщения EurekaLog?

A: В простейшем случае - идите на вкладку "Message Texts" в опциях проекта EurekaLog. Переведите сообщения на желаемый язык. Вы также можете сохранить перевод в коллекцию, чтобы использовать его в другом проекте. Перед тем, как делать свой перевод - поищите на нашем форуме: быть может кто-то уже выложил свой вариант перевода (а если вы сделали свой перевод - вы можете выложить его на форуме).

Вы также можете переключать язык в run-time, используя метод LoadCustomizedTextsFromFile класса TEurekaModuleOptions, например:
uses
  ExceptionLog;
...
  CurrentEurekaLogOptions.LoadCustomizedTextsFromFile(ExtractFilePath(Application.ExeName)  + 'Languages\SomeLang.etf');

etf-файл - это коллекция сообщений, которую вы сохранили на вкладке "Message Texts". Вы можете найти его в папке %AppData%\EurekaLog\.

Если вы хотите использовать другие утилиты для локализации (типа TsiLang или dxGetText) или ITE – то, хотя у нас нет прямой поддержки в EurekaLog v6 (планируется в v7), но вы можете использовать обходной путь типа:
uses
  ExceptionLog;
...
  CurrentEurekaLogOptions.CustomizedTexts[mtInformationMsgCaption] := 'Какое-то сообщение от движка локализации';
  … // тут другие константы mtXXX.

7 комментариев :

  1. Спасибо, статья очень пригодилась

    ОтветитьУдалить
  2. А можно ли в EurekaLog отфильтровать утечки памяти с помощью компонента TEurekaLog или ещё как-то?

    ОтветитьУдалить
  3. С помощью компонента - конечно нет. Ведь проверка утечек происходит в самый последний момент перед выходом из программы, когда никакого компонента уже не существует.

    А так, отфильтровать утечки можно переопределив обработчик утечек. См. http://news.eurekalog.com/showpost.php?p=8846&postcount=7 и http://news.eurekalog.com/showpost.php?p=10533&postcount=10

    ОтветитьУдалить
  4. Что то я установил ее. Через почту не отправляется. Логи не сохраняет ( зделал как у вас на скриншоте) . МОжете подсказать в чем может быть проблема ?
    И ещо одно - можно ли как то отключить "что случилось" что бы юзеры ошибки не смотрели ?

    ОтветитьУдалить
  5. >>> Через почту не отправляется

    Хоть бы сказали каким методом отправляете.

    В любом случае, на вкладке Send options есть галка "Show success/failure" - можно поставить для показа сообщений об ошибках.

    Кстати, письма, отправленные через SMTP Server многие почтовики любят записывать в спам - проверьте. Настройте фильтр, если это так.

    >>> Логи не сохраняет

    Не там ищите. Выводите в текущую папку (пустое поле "Log file output path"). Либо запускайте поиск *.elf по диску.

    >>> можно ли как то отключить "что случилось"

    Сбросить "Show 'Details' button", если я правильно понял, о чём идёт речь.

    P.S. На будущее: это персональный блог. Тех-поддержка EurekaLog находится здесь.

    ОтветитьУдалить
  6. А как самому добавить email и комментарий в отчет?
    Т.е. когда используешь их окно, то там есть поля для ввода. а если отправляешь отчет сам, то как их добавить?

    спасибо

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

    ОтветитьУдалить

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и (опционально) ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

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