Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // See also: http://pastebin.com/9P0PJcyc - "how to ignore particular exception"
- // You may want to log catched exceptions from your "except" blocks.
- // The best way to do it - is to insert a manual call to logging to each "except" block which you want to log.
- // This approach is illustrated here: http://pastebin.com/ACtr0r6S or http://pastebin.com/XWpyDuw6
- // Please, use this approach when possible.
- // Sometimes you may want to log all exceptions in your application.
- // For example, if you have too many already written code,
- // or if you are using 3rd party code which is not under your control.
- // Then you can use "Catch handled exceptions" option to globally trap all exceptions, including handled exceptions.
- // -= Important Note =-
- // Use "Catch handled exceptions" option with caution.
- // Never enable this option for production WITHOUT altering processing for handled exceptions.
- // Consider this code:
- for File in Files do
- try
- // ... try to read "File" file ...
- except
- on E: EStreamError do // <- E is catched by your code, thus it is called "handled" exception
- CorruptedFiles.Add(File);
- // <- other exceptions classes are not handled by your code, thus it is called "unhandled" exceptions
- end;
- if CorruptedFiles.Count > 0 then
- Application.MessageBox('The following files are corrupted: ' + CorruptedFiles.Text, 'Error.', MB_OK or MB_ICONSTOP);
- // The above code EXPECTS exceptions coming from guarded code block.
- // The code establish a recovery strategy for a certain class of exceptions (EStreamError).
- // If you enable "Catch handled exceptions" option - such exceptions will be processes by EurekaLog.
- // The code in question DOES NOT expecting that.
- // It certainly does not expect error dialogs, long delays (UI, sending, etc.).
- // Therefore, you must either enable "Catch handled exceptions" option only for debugging purposes
- // OR alter processing of handled exceptions.
- // -= end of note =-
- // You must perform the following 3 steps to log all handled exceptions.
- // 1. Enable "Catch handled exceptions" option.
- // 2. Use the following event handler:
- procedure LogHandledExceptions(const ACustom: Pointer; AExceptionInfo: TEurekaExceptionInfo; var AHandle, ACallNextHandler: Boolean);
- begin
- // If exception is handled - change processing logic
- if AExceptionInfo.Handled then
- begin
- LogException(AExceptionInfo, AHandled); // <- see below: option 3a or 3b
- Exit;
- end;
- // Unhandled exceptions remains unaltered
- end;
- initialization
- // Note that LogHandledExceptions will not be called for handled exceptions WITHOUT checked "Catch handled exceptions" option
- RegisterEventExceptionNotify(nil, LogHandledExceptions);
- end.
- // 3a. Use the following logging code:
- procedure LogException(AExceptionInfo: TEurekaExceptionInfo; var AHandle: Boolean);
- var
- LogBuilder: TBaseLogBuilder;
- LogFileName: String;
- begin
- // Create a generator for log content.
- // You may use default class for your application (LogBuilderClass)
- // Or a specific class (TLogBuilder, TXMLLogBuilder or your own descendant)
- LogBuilder := LogBuilderClass.Create(AEI);
- try
- // File name to save bug report to.
- // You may use AEI.BugIDStr, if you want to save each report into individual file.
- LogFileName := ExpandEnvVars(AEI.Options.OutputLogFile(''));
- // Generate and save bug report. File will be overwritten.
- LogBuilder.SaveToFile(LogFileName);
- finally
- FreeAndNil(LogBuilder);
- end;
- // Disable EurekaLog for this exception
- AHandle := False;
- end;
- // 3b. Or you can use the following logging code:
- procedure LogException(AExceptionInfo: TEurekaExceptionInfo; var AHandle: Boolean);
- begin
- // Set options for "silent" exception
- AExceptionInfo.Options.ExceptionDialogType := edtNone; // no dialog
- AExceptionInfo.Options.SenderClasses := ''; // no sending
- AExceptionInfo.Options.AutoCrashOperation := tbNone; // no autocrash counting
- AExceptionInfo.Options.SaveLogFile := True; // save bug report to disk
- AExceptionInfo.Options.ExceptionsFilters.Clear; // ignore exception filters
- // Log each exception to individual files
- if ExtractFileExt(AExceptionInfo.Options.OutputPath) <> '' then // if report path contains file name - delete it
- AExceptionInfo.Options.OutputPath := ExtractFilePath(AEI.Options.OutputPath);
- AExceptionInfo.Options.loAddBugIDInLogFileName := True;
- AExceptionInfo.Options.loAddComputerNameInLogFileName := False;
- AExceptionInfo.Options.loAddDateInLogFileName := False;
- AExceptionInfo.Options.soExcCount := True;
- AExceptionInfo.Options.ErrorsNumberToSave := 1;
- AExceptionInfo.Options.loNoDuplicateErrors := True;
- AExceptionInfo.Options.soAppVersionNumber := True; // <- this assumes that you are using version info; comment this otherwise
- AExceptionInfo.Options.loDeleteLogAtVersionChange := True; // <- this assumes that you are using version info; comment this otherwise
- AExceptionInfo.Options.loSaveProcessesSection := False;
- // Log only exception in current thread
- AExceptionInfo.Options.boPauseRTLThreads := False;
- AExceptionInfo.Options.boPauseWindowsThreads := False;
- AExceptionInfo.Options.csoShowWindowsThreads := False;
- AExceptionInfo.Options.csoShowRTLThreads := False;
- AExceptionInfo.Options.csoShowELThreads := False;
- // Do not change AHandle - let EurekaLog to process exception
- end;
- // -= Differences between 3a and 3b =-
- // 3a manually logs exceptions and fully disables EurekaLog for it.
- // 3b reconfigures exception and let normal flow of EurekaLog code to process it according to altered options.
- // Use 3a when you just need a simple .el file for exception.
- // Use 3b when you need some of EurekaLog's features (such as counting duplicates).
- // It is best to stick with option 3a when possible - to minimize overhead of processing handled exceptions.
- // Remember, some code may use exceptions a lot
- // (for example, a certain well-known components set uses exceptions in OnDraw handler -
- // which means insane amount of exceptions during normal workflow of application;
- // adding processing overhead for such exceptions may greatly slow down your application).
- // Another "gotcha" when using logging of handled exceptions:
- // You may log handled exceptions into individual bug report files,
- // then attach these files to bug report for unhandled exception.
- // This will deliver all handled exceptions bug reports to you.
- // For example:
- uses
- SyncObjs;
- var
- HandledExceptionsFiles: TStringList;
- HandledExceptionsFilesCS: TCriticalSection; // <- protects access to global HandledExceptionsFiles in multi-threaded application
- procedure LogException(AExceptionInfo: TEurekaExceptionInfo; var AHandle: Boolean);
- var
- LogFileName: String;
- begin
- // ...
- // Construct file name to save .el bug report to
- LogFileName := ExtractFilePath(ExpandEnvVars(AEI.Options.OutputLogFile(''))) + 'Handled.el'; // <- just an example
- // Remember this file:
- HandledExceptionsFilesCS.Enter;
- try
- if HandledExceptionsFiles = nil then
- begin
- HandledExceptionsFiles := TStringList.Create;
- HandledExceptionsFiles.Sorted := True;
- HandledExceptionsFiles.Duplicates := dupIgnore;
- end;
- HandledExceptionsFiles.Add(LogFileName);
- finally
- HandledExceptionsFilesCS.Leave;
- end;
- // ...
- // <- Use LogFileName to save bug report, e.g. LogBuilder.SaveToFile(LogFileName) or AEI.Options.OutputPath := LogFileName;
- // ...
- end;
- // Service routine: cleanups HandledExceptionsFiles with deleting all files
- procedure DeleteHandledExceptionsFiles;
- var
- X: Integer;
- begin
- HandledExceptionsFilesCS.Enter;
- try
- if HandledExceptionsFiles = nil then
- Exit;
- for X := 0 to HandledExceptionsFiles.Count - 1 do
- DeleteFile(HandledExceptionsFiles[X]);
- FreeAndNil(HandledExceptionsFiles);
- finally
- HandledExceptionsFilesCS.Leave;
- end;
- end;
- procedure AttachHandledReports(const ACustom: Pointer; AExceptionInfo: TEurekaExceptionInfo; const ATempFolder: String; AAttachedFiles: TStrings; var ACallNextHandler: Boolean);
- var
- X: Integer;
- DestFileName: string;
- begin
- HandledExceptionsFilesCS.Enter;
- try
- if HandledExceptionsFiles = nil then
- Exit;
- // Attach all files from HandledExceptionsFiles
- for X := 0 to HandledExceptionsFiles.Count - 1 do
- begin
- DestFileName := ATempFolder + ExtractFileName(HandledExceptionsFiles[X]);
- if CopyFile(PChar(HandledExceptionsFiles[X]), PChar(DestFileName), True) then
- AAttachedFiles.Add(DestFileName);
- end;
- // Files are attached and no longer needed - delete them
- DeleteHandledExceptionsFiles;
- finally
- HandledExceptionsFilesCS.Leave;
- end;
- end;
- initialization
- HandledExceptionsFilesCS := TCriticalSection.Create;
- // "Pack send files into single file (.elp)" option is checked?
- if CurrentEurekaLogOptions.sndPack then
- RegisterEventZippedFilesRequest(nil, AttachHandledReports) // if yes - add reports inside .elp
- else
- RegisterEventAttachedFilesRequest(nil, AttachHandledReports); // otherwise - add reports side-by-side with .el
- finalization
- DeleteHandledExceptionsFiles;
- FreeAndNil(HandledExceptionsFilesCS);
- end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement