Use TEurekaLogEvents when you want to attach EurekaLog callbacks in the form designer or keep them
with a particular form, frame or data module. It is optional: the component subscribes to events; it
does not enable EurekaLog or replace project configuration.
The choice is mostly about lifetime. A component subscription exists only while its container is
alive. For handling that must work before forms are created or after they are destroyed, register a
plain procedure through EEvents instead (chapter 7). Neither route makes callbacks main-thread-only.
This chapter covers selecting a host and wiring callbacks. Section 9.3 also covers a different,
easily confused component: VCL's TApplicationEvents, which can intercept exceptions before automatic
EurekaLog handling. Individual EurekaLog event contracts are in chapter 7.
9.1 What the component is
The non-visual component is declared in EComponent:
TEurekaLogEvents = class(TComponent); // EComponent
It has no window or visual role. Assign its events through the Object Inspector or in code, just
as you would assign other component events. Multiple TEurekaLogEvents components are allowed.
The important difference from a process-wide subscription is that each one lives and dies with its
container; section 9.4 explains the resulting coverage gaps.
9.2 What it exposes to code
The documented surface consists of fifteen event wrappers. They have the same purposes and
callback rules as their EEvents counterparts; the component does not define a separate reporting
pipeline. Use this map to choose an event, then use chapter 7 for its full signature and parameters.
While an exception is being raised and handled
| Event | What the events overview says it is for |
|---|---|
OnRaise |
fires on each exception raising |
OnExceptionNotify |
fires on each exception handling |
OnExceptionAction |
fires for exception processing stages; allows you to fine-control exception handling |
OnExceptionError |
fires on any error during exception processing |
Start with OnExceptionNotify when deciding whether EurekaLog should handle an exception. By
default it fires for exceptions not handled by application code; enabling "Catch handled exceptions"
also includes handled ones. Inspect AExceptionInfo.Handled to distinguish them.
While the report is being built and sent
| Event | What the events overview says it is for |
|---|---|
OnCustomDataRequest |
include additional data into bug report (text) |
OnCustomWebFieldsRequest |
customize request to web server or bug tracker with additional custom data |
OnCustomBugID |
customize BugID by supplying a sub-ID or replacing it completely with your own values |
OnCustomFileName |
allows you to alter any file name |
OnReproduceRequest |
supply a custom steps-to-reproduce data |
OnBeginReportGen |
fires before bug report generating |
OnEndReportGen |
fires after bug report generating |
OnBeginReportGen and OnEndReportGen share one handler type in EEvents, but are separate
component events. That shared type receives the log builder as plain TObject and needs a
type cast to TBaseLogBuilder. The similarly named type in ELogBuilder takes
TBaseLogBuilder directly and avoids the cast where that type is accepted. Use the signature
required by the registration point; the two types are not interchangeable.
The files that travel with the report
| Event | What the events overview says it is for |
|---|---|
OnAttachedFilesRequest |
include additional files into bug report (separate files) |
OnZippedFilesRequest |
include additional files into zipped bug report |
The pair splits by destination: the files listed by OnAttachedFilesRequest are sent as separate files
alongside the report, while the files listed by OnZippedFilesRequest are put inside the packed
report (the .elp file).
The error dialog
| Event | What the events overview says it is for |
|---|---|
OnCustomButtonClick |
fires when the "Custom" button is clicked in the error dialog |
The password for encrypted debug information
| Event | What the events overview says it is for |
|---|---|
OnPasswordRequest |
supply a password to decrypt call stacks |
The event's own page widens that one line: the password is what lets EurekaLog decrypt debug information
that was saved encrypted. The handler may ask the user for it at run time or read it from the
application's configuration, and the event is not called at all when the password has already been
obtained by some other means (from a local cache, or from the --el_password= command line argument,
for instance).
Two notes on the list
Two naming boundaries matter when wiring code:
OnHelpButtonClickexists inEEventsbut is not among the documented component events. Register it throughEEventsusing section 7.7 rather than inventing a component property.- The component property is
OnCustomWebFieldsRequest(plural), notOnCustomWebFieldRequest.
The method type determines the handler's signature: TELEvRaiseMeth for OnRaise,
TELEvExceptionNotifyMeth for OnExceptionNotify, and so on. OnBeginReportGen and
OnEndReportGen share a type. The following example uses OnExceptionNotify.
9.3 Attaching a handler
The designer route
In a project already configured for EurekaLog (chapter 1):
- Drop
TEurekaLogEventson the chosen form or data module. - Select its Events page in the Object Inspector.
- Double-click
OnExceptionNotifyto create a method, or choose an existing compatible method. - Put only callback-safe code in that method: use the supplied exception and avoid unsynchronized forms or mutable globals.
The code route
If a live container already owns EurekaLogEvents1 and declares the handler method, assign the
property from that container's initialization code, for example its OnCreate handler:
// On the container that owns the component - a form, a frame or a data module
EurekaLogEvents1.OnExceptionNotify := EurekaLogEvents1ExceptionNotify;
The handler is a method of the container, and its parameters are those of the EEvents method
type for the event - the "...Meth" type. For OnExceptionNotify that declaration is:
TELEvExceptionNotifyMeth = procedure(
AExceptionInfo: TEurekaExceptionInfo;
var AHandle: Boolean;
var ACallNextHandler: Boolean
) of object; // EEvents
The type's first parameter, TEurekaExceptionInfo, is declared in the EException unit - EEvents
declares the event types only - so a unit that declares such a handler needs both of those units in its
uses clause.
The parameters are documented as follows: AExceptionInfo is input, "information about exception";
AHandle is output, True (the default) meaning process the exception with EurekaLog, False
meaning process it with the standard exception handler; ACallNextHandler is output, True (the
default) meaning call the next registered event handler, False meaning do not. Set
ACallNextHandler to False if you set AHandle to False.
For an existing TDataModule1, let the designer declare the method and place this implementation in
the data module's unit. Include EComponent, EException and EEvents in the unit as needed by the
component field and handler declaration. This example leaves handling and chaining unchanged:
procedure TDataModule1.EurekaLogEvents1ExceptionNotify(AExceptionInfo: TEurekaExceptionInfo;
var AHandle, ACallNextHandler: Boolean);
begin
if AExceptionInfo <> nil then
AExceptionInfo.AdditionalInfo := 'Diagnostic context from the reporting module';
end;
This changes AdditionalInfo, which can override the dialog message under UseExceptionComments
(section 8.9). Use OnCustomDataRequest for a named report field instead. No transfer of
AExceptionInfo ownership to this callback is documented. Use it during the callback; do not
free it or assume it will remain valid for later UI work.
For OnCustomDataRequest, do not assume that ALogBuilder: TObject and
ALogBuilder: TBaseLogBuilder are interchangeable handler parameters. Follow the signature
of the registration point and cast only when needed (section 7.4).
The recommended alternative is not to use the component at all: register the handler through
EEvents from the initialization section of a unit of your own. A plain procedure registered
there belongs to no object, which is what makes it the right route when the handler has to be
there before the first container exists or after the last one is gone.
A method registered the same way is tied to the object that owns it: registration from
FormCreate requires a matching UnregisterEvent... call in FormDestroy. Neither ordinary
route alone covers shutdown leak reporting: much of the application and its registrations have
already been finalized at that point. Leak callbacks must be registered for that phase and
avoid finalized data, as shown in section 7.8 and chapter 22.
Keeping VCL application exception handlers
If reporting stopped after adding Application.OnException or TApplicationEvents, inspect that
integration before changing report options. EurekaLog 7 respects an assigned
Application.OnException: it treats the assignment as a request for application code to handle
exceptions, rather than taking them over automatically.
TApplicationEvents installs an Application.OnException handler of its own—even when its
OnException property is empty. In some Delphi versions, merely including VCL.AppEvnts
(AppEvnts on older versions) can install that interception without any component instance.
The VCL event is not multicast; adding a component later does not preserve two independent
automatic handlers.
Choose one route deliberately:
| What you need | Integration |
|---|---|
| No separate application exception handler | Remove your Application.OnException assignment. Move custom reporting work to EurekaLog's OnExceptionNotify. |
No TApplicationEvents component |
Remove it and remove the unused VCL.AppEvnts/AppEvnts unit as well; deleting the component alone may be insufficient. |
Keep TApplicationEvents |
Assign its OnException event and explicitly forward the supplied exception to EBase.HandleException. |
Keep a directly assigned Application.OnException |
Forward from that handler. EBase.HandleException(E) uses its argument; ExceptionManager.ShowLastExceptionData is the documented alternative for the current active exception. |
For the component route, create ApplicationEvents1.OnException through the Object Inspector in an
existing VCL form TMainForm. The form unit needs System.SysUtils for Exception in the interface
uses list and EBase in the implementation uses list; retain Vcl.AppEvnts for the component.
The designer supplies the method declaration and event assignment. Replace the generated method
body with this:
procedure TMainForm.ApplicationEvents1Exception(Sender: TObject; E: Exception);
begin
EBase.HandleException(E);
end;
This is a VCL exception-boundary adapter, not a TEurekaLogEvents.OnExceptionNotify callback.
Do not call it from OnExceptionNotify, where you are already inside EurekaLog processing.
It does not free the VCL-supplied exception, alter activation or guarantee any particular dialog or
send action. Use an enabled, processed project and the desired reporting options; do not install
both forwarding routes and expect duplicate processing to be useful.
An unassigned TApplicationEvents.OnException can still appear to work when the RTL falls back to
Application.ShowException: EurekaLog can intercept that call if Use low-level hooks is enabled.
That conditional fallback is not a substitute for an explicit forwarding handler. After the change,
exercise an unhandled exception from an ordinary VCL event outside the IDE debugger and check the
configured report output, not just whether a dialog appears. If it still fails, follow chapter 5
to distinguish installation, activation, interception and report-processing failures.
9.4 The lifetime rule that decides where the component goes
A component handler is unavailable before its container exists and after it is destroyed. This applies to forms, frames and data modules, regardless of visibility. In particular, a component is a poor foundation for an application-wide replacement error dialog: initialization/finalization errors and errors in a form constructor can fall outside its lifetime.
An early-created, late-destroyed data module covers the interval between those events, not the entire process lifetime. If you need broader coverage, use a plain procedure registered from a unit's initialization section, with the lifetime rules in chapter 7. If you choose a component, the documented recommendation is the main form. Multiple components are permitted; that does not remove any individual container's lifetime boundary.
9.5 What a handler attached this way must respect
Two rules apply to any EurekaLog event handler - including the ones the component creates - and one applies to the component itself.
The thread. All EEvents handlers share this restriction:
Any event is called from the context of exception thread, which may be not the main thread of application. Thus, it's highly recommended to avoid using any global-like data and to avoid access VCL objects. If you still need to do any of that - please use proper thread synchronization for globals and
Synchronizemethod for VCL access.
Never assume the thread the handler will run in: an event handler may be called from a background thread even in a single-threaded application, and a stack overflow exception will force all event handlers to run from a background service thread. A handler that touches no global needs no synchronization. Immutable global data that never changes and needs no finalization can be read from any thread, and a managed global that is initialized before the handler is registered and never changed while it lives can be read too. Synchronization is needed for data that can change while the handler is alive. A component on a form makes no difference to any of this: the container's events do not move the handler to the main thread.
The options. If you change EurekaLog's settings from an event handler, alter the local
options (AExceptionInfo.Options) and not the global ones (CurrentEurekaLogOptions). That
applies to events whose handler receives an exception information object. The object can be
nil for OnRaise, OnExceptionAction, OnExceptionError and OnCustomWebFieldsRequest,
and OnPasswordRequest has no such parameter at all. Check before reading or writing through
it. Attaching the handler through a component does not change these restrictions.
The component activates nothing. Enable EurekaLog for the project through
Project → EurekaLog Options, choose the appropriate application type and rebuild through the
configured toolchain (chapters 1–2). Merely dropping TEurekaLogEvents or importing EComponent
does not install reporting.
9.6 Removing it again
When removing EurekaLog, remove both the TEurekaLogEvents component from the form and the
EComponent unit from the same form's uses clause. Removing the component in the designer
is not the whole job, because the unit reference lives in the source.
9.7 Boundaries of this interface
- Programmatic creation is not a separate EurekaLog lifecycle API. No custom constructor or EurekaLog-specific ownership contract is specified. Use ordinary component ownership; the code above assigns events on an already-owned component.
- Multiple components do not have a documented callback order. If order matters, use explicit
EEventsregistration andAFirst(section 7.2) instead of relying on form creation order. - Detaching a handler is distinct from removing EurekaLog. Assigning
nilto an event property clears that Delphi property. For direct registrations, call the matchingUnRegisterEvent...routine before the handler's owner dies. Removing EurekaLog from a project also requires removal of component instances andEComponentreferences, as section 9.6 explains. - Event behavior belongs to the shared callback contract. Chapter 7 supplies the full signatures, nil cases, chaining and stage semantics; this chapter does not define different ones.