Recording Events

An Event is used as a counter for some activity that occurs within the application. Events are recorded by using Event objects that can be created at the top level of the Listener:
Listener listener("appName", "appVersion", NULL, NULL);
Event *toplevelEvent = listener->lookupEvent(eventClass, "eventName", [optional] includeParent);
Or as a subordinate to a Container:
Container *eventContainer = listener->lookupContainer("containerName");
Event *subordinateEvent = eventContainer->lookupEvent(eventClass, "eventName", [optional] includeParent);
or as a sub-Event (subordinate to another Event):
Event *subEvent = subordinateEvent->lookupEvent("eventName", [optional] includeParent);

Each Event object has a 64-bit counter that increases cumulatively over the lifetime of the object (which is also the lifetime of the Listener). The initial value of the counter is set to zero and can be incremented by using the recordEvent member function.

The eventClass parameter of the constructor is an EventClass enumeration constant that specifies the class of the Event. This parameter is not specified when you are creating a sub-Event of another Event object because the event class of the sub-Event must be the same as the one employed by the parent Event object. The application implements an Event as class RPC to record top-level client requests, or as class USER to record any other type of Event or operation that is occurring in the application. In addition to these two class types, the Listener also automatically generates data in three other classes: DISK, NETWORK, and CPU.

The eventName is a string that provides the name for the Event. The constructor is overloaded to allow the string to be passed as Unicode const wchar_t * that contains any printable UTF-8 characters, excluding the newline character. The includeParent parameter is an optional Boolean value (default is false), which indicates whether the recordEvent member function of the parent Event object is called when the counter for the sub-Event is incremented.

Creating Subordinate Objects

The created application creates subordinate objects for the Event, including Meters, Accumulators, or other Events, called sub-Events.

Accumulators depend on the counter that is maintained by their parent Event object and use it for computing the average accumulation value over time. For more information about working with Accumulators, see Recording Values with Accumulators.

Meters are similar to Accumulators; except they maintain absolute values and can be used for reporting the aggregation intervals of these values over time. For more information about working with Meters, see Reporting Performance Data with Meters.

Creating sub-Events

A sub-Event automatically inherits the event class of the parent Event object and can be used to represent a significant activity that sometimes or always occurs while it is running the higher-level Event, or it can also represent a refined Event counter.

For example, suppose that the application is configured to respond to an RPC Event named RPCEventOne and that when it is servicing RPCEventOne, a significant subroutine SubroutineOne is sometimes called. The application can choose to record the number of times SubroutineOne is called, along with the total processing time for the subroutine. In this case, the application would implement the following Events:

Event *RPCEventOne = listener->lookupEvent(RPC, "RPC Event One", true);
Event *RPCSubEventOne = RPCEventOne->lookupEvent("RPC SubEvent One", true);
Note: Separate Duration objects can also be declared for the duration Accumulators that are associated with each of these Event objects. For more information, see Measuring Elapsed Time with Durations.

Auto-incrementing Parent Event Counters

Sub-Events can also be created such that when their recordEvent member function is called to increment the Event counter, then the counter for the parent Event is also automatically incremented by the same amount. This type of sub-Event is created by specifying true for the includeParent parameter of the constructor.

As an example, suppose the application must count creations of various types of objects. The application would implement Events and sub-Events similar to the following examples:

Event *creations = listener->lookupEvent(USER, "creations");
Event *documentCreations = creations->lookupEvent("created documents", true);
Event *folderCreations = creations->lookupEvent("created folders", true);

Assuming that these definitions represent all of the possible types of object creation operations, the application would never directly use the creations Event object. In addition, the pointer to the creations Event object is discarded by the application because each time a document is created, the recordEvent member function of the documentCreations Event object is called, and each time a folder is created, the recordEvent function of the folderCreations Event object is called. This implementation causes the total number of creations that are run to be automatically recorded in the creations Event counter. Additionally, it can "drill down" in a Manager to see the number of each type of creation that were generated.

The auto-increment function is recursive. If the parent of a sub-Event is also a sub-Event that is configured to auto-increment the parent Event counter, then all three Event counters would be incremented by a single call to recordEvent.