http://myhost:aPort/cgi-bin/WebObjects/MyApp.woa/wa/WOEventSetup
On the WOEventSetup page, you can see all families of events that are registered for the application. Since the event classes are registered dynamically as the program executes, it is a good idea to "warm up" an application before accessing WOEventSetup.
The page lists the registered event classes, their subcategories, and a description of the kinds of events that can be logged. For instance, the EOEditingContext event class logs events for the saveChanges and objectsWithFetchSpecification methods. Logging for each class can be enabled and disabled with the corresponding check box; it isn't possible to disable individual subcategories of an event class.
The logging mechanism is extremely fast and memory efficient. A standard 300MHz G3 can log more than 300,000 events per second, so event logging overhead is negligible compared to the time required to generate dynamic web pages.
User Defaults
WOEventDisplay page
http://myhost:aPort/cgi bin/WebObjects/MyApp.woa/wa/WOEventDisplay
On this page, events can be viewed in four different ways:
Note that since a page is also a component, a page with no dynamic subcomponents seems as if it's nested one level too deep. This is the correct behavior.
In any of these displays, if an event or event group has subevents, it can be expanded by clicking the hyperlink or triangle image.
Each view orders events by duration (in milliseconds) from the longest to the shortest. Aggregation induces rounding errors, which are a maximum of 1ms per event. In other words, an aggregate event consisting of ten events has at most 1 ms deviation from the actual run time; however, manually adding ten individual events as displayed in the table might have up to a 10 ms deviation. Therefore, any displayed sum is always more accurate than adding up the durations of individual events. Also note that the sub events of an event branch doesn't necessarily add up to the duration of the branch event the branch event's duration might be larger. This because the parent event generally consists of more than just calling the methods causing the sub events.
Custom Event Logging
To create a custom event:
For example, to log events for a custom adaptor , say MyAdaptor, create an EOEvent subclass named MyAdaptorEvent. subclass doesn't usually have to override any of the inherited methods, but you can customize the default behavior.
An event's description file defines the event categories and subcategories
used in the WOEventDisplay page. The file's contents is a dictionary in
plist format. For the MyAdaptorEvent class, the file's name is
MyAdaptorEvent.description
, and it might look like the following:
{
EOEventGroupName ="MyAdaptor Event ";
connect ="Connect ";
openChannel ="Open Channel ";
evaluateExpression ="Evaluate Expression ";
fetchRow ="Fetch Row ";
commitTransaction ="Commit Transaction ";
}
Typically you can register an event class in the static constructor of the class whose code you are instrumenting MyAdaptor in this example.
public static class MyAdaptorEvent extends EOEvent {
protected static final String Connect = "connect";
protected static final String OpenChannel = "openChannel";
// etc.
public CustomEvent() {
super();
}
public CustomEvent(String type) {
super();
setType(type);
}
}
public static class MyAdaptorEventLoggingEnabler extends Object implements EOEventCenter.EventRecordingHandler {
public void setLoggingEnabled(boolean isLogging, Class aClass) {
_IsEventLoggingEnabled = isLogging;
}
}
static {
EOEventCenter.registerEventClass(MyAdaptorEvent.class, new MyAdaptorEventLoggingEnabler());
}
As in this example, you might want to define string constants for the keys in the event's description dictionary.
In any method you want to instrument, following code to be added, substituting the appropriate event key. This code instruments the "connect" event of MyAdaptorEvent.
EOEvent e = null;
//Setup and start logging
if (_IsEventLoggingEnabled) {
e = new MyAdaptorEvent(MyAdaptorEvent.OpenChannel);
EOEventCenter.markStartOfEvent(e, "openChannel()");
}
//Code to be timed goes here.
//Finish logging.
if (e != null) {
EOEventCenter.markEndOfEvent(e);
}
The second argument to newEventOfClass is an event key
corresponding with an entry in the .description
file. The
corresponding value is used in the Title column of the WOEventDisplay page.
If the argument isn't a key in the description dictionary,
newEventOfClass uses the argument instead.