At runtime, your add-on component might perform operations that affect the behavior and performance of your system. For example, your component might start a thread of control, receive a request from a service, or request a connection from a connection pool. Monitoring the statistics that are related to these operations helps a system administrator maintain the system.
To provide statistics to Enterprise Server, your component must define events for the operations that generate these statistics. At runtime, your component must send these events when performing the operations for which the events are defined. For example, to enable the number of received requests to be monitored, a component must send a “request received” event each time that the component receives a request.
A statistic can correspond to single event or to multiple events.
Counter statistics typically correspond to a single event. For example, to calculate the number of received requests, only one event is required, for example, a “request received” event. Every time that a “request received” event is sent, the number of received requests is increased by 1.
Timer statistics typically correspond to multiple events. For example, to calculate the time to process a request, two requests, for example, a “request received” event and a “request completed” event.
Defining statistics that are to be monitored involves the following tasks:
An event provider defines the types of events for the operations that generate statistics for an add-on component.
To define an event provider, write a JavaTM language interface that defines the types of events for the component. In the interface, define one method for each type of event that is related to the component.
You are not required to implement the event provider interface. After you register the event provider, Enterprise Server generates the implementation class at runtime for you. For more information, see Registering an Event Provider.
If you overload a method in your implementation, annotate each form of the method with the @org.glassfish.flashlight.provider.annotations.ProbeName annotation to uniquely identify the event type. Set the value element of the @ProbeName annotation to the name of the event type.
If you do not annotate a method, the name of the event type is the method name. Therefore, you are not required to annotate methods that are not overloaded.
To enable methods in an event listener to select a subset of values, annotate each parameter in the method signature with the org.glassfish.flashlight.provider.annotations.ProbeParam annotation. Set the value element of the @ProbeParam annotation to the name of the parameter.
This example shows the definition of the TxManager interface. This interface defines events for the start and end of transactions that are performed by a transaction manager.
The methods in this interface are as follows:
This method sends an event to indicate the start of a transaction. The name of the event type that is associated with this method is begin. A parameter that is named txId is passed to the method.
This method sends an event to indicate the end of a transaction. The name of the event type that is associated with this method is the method name. A parameter that is named outcome is passed to the method.
import org.glassfish.flashlight.provider.annotations.ProbeName; import org.glassfish.flashlight.provider.annotations.ProbeParam; public interface TxManager { @ProbeName("begin") public void onTxBegin( @ProbeParam("{txId}") String txId ); public void onCompletion( @ProbeParam("{outcome}") boolean outcome ); }
Registering an event provider generates a class that implements the event provider interface. Enterprise Server provides the org.glassfish.flashlight.provider.ProbeProviderFactory factory class that generates the event provider class at runtime. To generate the class, Enterprise Server uses the ASM framework for manipulating and analyzing Java byte codes.
By default, a nonoperational implementation of the methods is created. If monitoring is not enabled, which means that no listeners are registered, the methods do not consume any computing resources, such as memory or processor cycles.
The ProbeProviderFactory.getProbeProvider method is an unstable interface and is subject to change.
To register an event provider, invoke the ProbeProviderFactory.getProbeProvider method in the class that represents your add-on component. In the invocation of the ProbeProviderFactory.getProbeProvider method, pass the following information as parameters to the method:
Your choice of name for the add-on component that is to send the event.
Your choice of name for the provider.
Your choice of name for the application that the add-on component represents. The application-name can be null.
The compiled class that is to implement your event provider interface. For example, if your event provider interface is named TxManager, specify the class as TxManager.class.
This example shows the code for registering the event provider interface TxManager for the add-on component that is represented by the class TransactionManagerImpl. The definition of the TxManager interface is shown in Example 5–1. The component name is tx and the provider name is TxManager. No application name is specified.
... import org.glassfish.flashlight.provider.ProbeProviderFactory; ... public class TransactionManagerImpl { ... @Inject protected ProbeProviderFactory probeProviderFactory; ... TxManager txProvider = probeProviderFactory.getProbeProvider( "tx", "TxManager", null, TxManager.class); ... }
At runtime, your add-on component might perform an operation that generates statistics. To provide statistics about the operation to Enterprise Server, your component must send an event of the correct type when performing the operation.
To send an event, invoke the method of your event provider class that is defined for the type of the event. Ensure that the method is invoked when your component performs the operation for which the event was defined. One way to meet this requirement is to invoke the method for sending the event in the body of the method for performing the operation.
This example shows the code for invoking the onTxBegin method to send an event of type begin. This event indicates that a component is about to begin a transaction. To ensure that the event is sent at the correct time, the onTxBegin method is invoked in the body of the begin method, which starts a transaction.
The declaration of the onTxBegin method in the event provider interface is shown in Example 5–1.
The creation of the txProvider object is shown in Example 5–2.
... public class TransactionManagerImpl { ... public void begin() { String txId = createTransactionId(); .... txProvider.onTxBegin(txId); //emit } ... }