Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Логгирование исключений с последующим их перевозбуждением.


Страницы:   1 2 3

>|< ©   (2010-11-26 16:33:00) 

Прошу мастеров просмотреть данный код на предмет подводных камней.
Будет ли он правильно работать и какие могут быть нюансы.
procedure TDMMain.KMSExceptionHandler(Sender: TObject; E: Exception);
var fn:string;
   LOB: TLOBLocator;
   MyBlobStream: TMemoryStream;
   ComponentName:string;

begin
 try
   try
     Fn := ExtractFilename(Application.ExeName)+'_'+
           Screen.ActiveForm.Name+
           FormatDateTime('_ddmmyyyy_hhnnss',now)+
           '_debug';
     MyBlobStream:= TMemoryStream.Create;
     DoGenerateScreenshot;

     LOB:= TLOBLocator.CreateTemporary(DMMain.OracleSession, otBLOB, True);
     try
       oqInsertError.ClearVariables;
       oqInsertError.SetVariable('V_FORM_NAME',Screen.ActiveForm.Name+':'+Screen.ActiveForm.Caption);
       oqInsertError.SetVariable('V_ERROR_TEXT',E.Message);
       oqInsertError.SetVariable('V_ID_USER',DMMain.UserID);
       oqInsertError.SetVariable('V_DATETIME',Now);
       oqInsertError.SetVariable('V_OSUSER_NAME',CollectUserName);
       oqInsertError.SetVariable('V_COMP_NAME',CollectComputerName);
       oqInsertError.SetVariable('v_exception_name', E.ClassName);
       if Sender is TComponent then
         ComponentName := TComponent(Sender).Name
         //TODO: Попытаться вытянуть из сендера текстовое заглавие  компонента, который возбудил ошибку
       else
         ComponentName := '<имя неизвестно>';
       oqInsertError.SetVariable('v_object_name',Sender.ClassName+':'+ ComponentName);
       MyBlobStream.Position := 0;
       LOB.CopyFrom(MyBlobStream, MyBlobStream.Size);
       oqInsertError.SetComplexVariable('V_SCREENSHOT', LOB);
       oqInsertError.Execute;
       DMMain.OracleSession.Commit;
     finally
       LOB.Free;
       MyBlobStream.Free;
     end;
   except
     on E_local:Exception do
     begin
         raise E_local.Create('Ошибка логгирования:'#10#13+ E_local.Message);
         MyBlobStream.SaveToFile(fn+'.jpg');
     end;
   end;
 finally
   Application.OnException := nil;
   raise E.Create('Произошло исключение, которое было записано в БД.');
   Application.OnException := KMSExceptionHandler;
 end;
end;


Сергей М.   (2010-11-26 17:40:00) [41]

Ну и логируй их себе на здоровье)
Зачем обнилять-то обработчик и потом восстанавливать ?
Или ты настольуо не уверен в своих телодвижениях, что боишься допуститиь в теле обработчика непредвиденное исключение ?)


&gt;|&lt;   (2010-11-26 17:39:00) [42]

Если не выключать обработчик, полагаю, возникнет циклическое исключение.


&gt;|&lt;   (2010-11-26 17:36:00) [43]


> Непонятно зачем эти пляски с бубном вокруг обниления и восстановления
> обработчика Application.OnException в теле самого обработчика
> ..

Капитан Очевидность спешит с ответом:
Для логирования ошибок:-)


Сергей М.   (2010-11-26 17:28:00) [44]


> Можно ли таким образом поступить?
> finally
>    Application.OnException := nil;
>    try
>     raise E;
>    finally
>      Application.OnException := KMSExceptionHandler;
>    end;
>  end;


Непонятно зачем эти пляски с бубном вокруг обниления и восстановления обработчика Application.OnException в теле самого обработчика ..


&gt;|&lt;   (2010-11-26 17:20:00) [45]

Можно ли таким образом поступить?
finally
   Application.OnException := nil;
   try
    raise E;
   finally
     Application.OnException := KMSExceptionHandler;
   end;
 end;


&gt;|&lt;   (2010-11-26 17:16:00) [46]

Вопрос остается открытым:
Каким образом перевозбудить исключение после записи его в лог?


&gt;|&lt;   (2010-11-26 17:14:00) [47]


> Весь код не смотрел, но вот здесь 2 ошибки:
>
> finally
>   Application.OnException := nil;
>   raise E.Create(...); // Е - это не класс, а экземпляр
> объекта.
>   Application.OnException := ... // Эта строка никогда не
> выполнится
> end;

в принципе, это ключевое место
тогда вопрос, как перевозбудить исключение, которое содержится в объекте E?
Можно ли написать следующим образом:
finally
  Application.OnException := nil;
   try
    raise // каким образом здесь перевозбудить исключение?
   finally
     Application.OnException := KMSExceptionHandler;
   end;
end;


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

Таки да, в приложении будут работать потоки, для которых будет своя обработка.
Цитирую:
"При использовании TThread у вас уже есть возможности для манёвра. Дело в том, что функция потока в TThread оборачивает вызов Execute в try/except. Любое исключение, сбежавшее из Execute, заносится в свойство FatalException потока. Исключение будет удалено в деструкторе TThread. А вы можете проанализировать этот код из события OnTerminate или из кода главного потока, например:

T := TMyThread.Create(False);
try

 // ... <- Выполняем какие-то действия. Поток в это время также выполняет работу.

 // Мы свою работу выполнили - ждём конца работы потока.
 T.WaitFor;
 // Анализируем: успешно ли завершился поток?
 if T.FatalException <> nil then // есть ошибка
 begin
   // Обработка ошибки потока.
 end;
finally
 FreeAndNil(T);
end;"


Сергей М.   (2010-11-26 16:50:00) [48]


> Rouse_ ©   (26.11.10 16:47) [5]


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


Если ты о TThread, то оч даже понятно - для формошлепов это сделано)


Rouse_   (2010-11-26 16:47:00) [49]

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


Сергей М.   (2010-11-26 16:44:00) [50]


> на предмет подводных камней


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


Юрий Зотов   (2010-11-26 16:43:00) [51]

Весь код не смотрел, но вот здесь 2 ошибки:

finally
  Application.OnException := nil;
  raise E.Create(...); // Е - это не класс, а экземпляр объекта.
  Application.OnException := ... // Эта строка никогда не выполнится
end;


Rouse_   (2010-11-26 16:42:00) [52]

вот это работать не будет:

  raise E.Create('Произошло исключение, которое было записано в БД.');
  Application.OnException := KMSExceptionHandler; <<< вызвано не будет


Rouse_   (2010-11-26 16:42:00) [53]

ну и вот это тоже :)
MyBlobStream.SaveToFile(fn+'.jpg');


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо