![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Логгирование исключений с последующим их перевозбуждением.
>|< © (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]Ну и логируй их себе на здоровье)
Зачем обнилять-то обработчик и потом восстанавливать ?
Или ты настольуо не уверен в своих телодвижениях, что боишься допуститиь в теле обработчика непредвиденное исключение ?)
>|< (2010-11-26 17:39:00) [42]Если не выключать обработчик, полагаю, возникнет циклическое исключение.
>|< (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 в теле самого обработчика ..
>|< (2010-11-26 17:20:00) [45]Можно ли таким образом поступить?
finally
Application.OnException := nil;
try
raise E;
finally
Application.OnException := KMSExceptionHandler;
end;
end;
>|< (2010-11-26 17:16:00) [46]Вопрос остается открытым:
Каким образом перевозбудить исключение после записи его в лог?
>|< (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');