Oracle GlassFish Server Add-On Component Development Guide Release 3.1.2 Part Number E24927-01 |
|
|
View PDF |
Monitoring is the process of reviewing the statistics of a system to improve performance or solve problems. By monitoring the state of components and services that are deployed in the GlassFish Server, system administrators can identify performance bottlenecks, predict failures, perform root cause analysis, and ensure that everything is functioning as expected. Monitoring data can also be useful in performance tuning and capacity planning.
An add-on component typically generates statistics that the GlassFish Server can gather at run time. Adding monitoring capabilities enables an add-on component to provide statistics to GlassFish Server in the same way as components that are supplied in GlassFish Server distributions. As a result, system administrators can use the same administrative interfaces to monitor statistics from any installed GlassFish Server component, regardless of the origin of the component.
The following topics are addressed here:
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 GlassFish 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.
GlassFish Server enables you to define an event provider in the following ways:
By writing a Java Class. Define an event provider this way if you have access to the source code of the component for which you are defining an event provider.
By writing an XML fragment. Define an event provider this way if you do not have access to the source code of the component for which you are defining and event provider.
To define an event provider, write a Java language class that defines the types of events for the component. Your class is not required to extend any specific class or implement any interfaces.
To identify your class as an event provider, annotate the declaration of the class with the org.glassfish.external.probe.provider.annotations.ProbeProvider
annotation.
To create a name space for event providers and to uniquely identify an event provider to the monitoring infrastructure of GlassFish Server, set the elements of the @ProbeProvider
annotation as follows:
moduleProviderName
Your choice of text to identify the application to which the event provider belongs. The value of the moduleProviderName
element is not required to be unique.
For example, for event providers from Oracle GlassFish Server, moduleProviderName
is glassfish
.
moduleName
Your choice of name for the module for which the event provider is defined. A module provides significant functionality of an application. The value of the moduleName
element is not required to be unique.
In GlassFish Server, examples of module names are web-container
, ejb-container
, transaction
, and webservices
.
probeProviderName
Your choice of name to identify the event provider. To uniquely identify the event provider, ensure that probeProviderName
is unique for all event providers in the same module.
In GlassFish Server, examples of event—provider names are jsp
, servlet
, and web-module
.
To define event types in an event provider class, write one method for each type of event that is related to the component. The requirements for each method are as follows:
The return value of the callback methods must be void.
The method body must be empty. You instantiate the event provider class in the class that invokes the method to send the event. For more information, see Sending an Event.
To enable the event to be used as an Oracle Solaris DTrace probe, each parameter in the method signature must be a Java language primitive, such as Integer
, boolean
, or String
.
Annotate the declaration of each method with the org.glassfish.external.probe.provider.annotations.Probe
annotation.
By default, the type of the event is the method name. If you overload a method in your class, you must uniquely identify the event type for each form of the method. To uniquely identify the event type, set the name
element of the @Probe
annotation to the name of the event type.
Note:
You are not required to uniquely identify the event type for 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.external.probe.provider.annotations.ProbeParam
annotation. Set the value
element of the @ProbeParam
annotation to the name of the parameter.
Example 5-1 Defining an Event Provider by Writing a Java Class
This example shows the definition of the TxManager
class. This class defines events for the start and end of transactions that are performed by a transaction manager.
The methods in this class are as follows:
onTxBegin
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.
onCompletion
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 end
. A parameter that is named outcome
is passed to the method.
import org.glassfish.external.probe.provider.annotations.Probe; import org.glassfish.external.probe.provider.annotations.ProbeParam; import org.glassfish.external.probe.provider.annotations.ProbeProvider; @ProbeProvider(moduleProviderName="examplecomponent", moduleName="transaction", probeProviderName="manager") public class TxManager { @Probe("begin") public void onTxBegin( @ProbeParam("{txId}") String txId ){} @Probe ("end") public void onCompletion( @ProbeParam("{outcome}") boolean outcome ){} }
To define an event provider, write an extensible markup language (XML) fragment that contains a single probe-provider
element.
To create a name space for event providers and to uniquely identify an event provider to the monitoring infrastructure of GlassFish Server, set the attributes of the probe-provider
element as follows:
moduleProviderName
Your choice of text to identify the application to which the event provider belongs. The value of the moduleProviderName
attribute is not required to be unique.
For example, for event providers from Oracle GlassFish Server, moduleProviderName
is glassfish
.
moduleName
Your choice of name for the module for which the event provider is defined. A module provides significant functionality of an application. The value of the moduleName
attribute is not required to be unique.
In GlassFish Server, examples of module names are web-container
, ejb-container
, transaction
, and webservices
.
probeProviderName
Your choice of name to identify the event provider. To uniquely identify the event provider, ensure that probeProviderName
is unique for all event providers in the same module.
In GlassFish Server, examples of event—provider names are jsp
, servlet
, and web-module
.
Within the probe-provider
element, add one probe
element for each event type that you are defining. To identify the event type, set the name attribute of the probe
element to the type.
To define the characteristics of each event type, add the following elements within the probe
element:
class
This element contains the fully qualified Java class name of the component that generates the statistics for which you are defining events.
method
This element contains the name of the method that is invoked to generate the statistic.
signature
This element contains the following information about the signature if the method:
return-type (paramater-type-list)
The return type of the method.
A comma-separated list of the types of the parameters in the method signature.
probe-param
The attributes of this element identify the type and the name of a parameter in the method signature. One probe-param
element is required for each parameter in the method signature. The probe-param
element does not contain any data.
The attributes of the probe-param
element are as follows:
type
Specifies the type of the parameter.
name
Specifies the name of the parameter.
return-param
The type
attribute of this element specifies the return type of the method. The return-param
element does not contain any data.
Example 5-2 Defining an Event Provider by Writing an XML Fragment
This example defines an event provider for the glassfish:web:jsp
component. The Java class of this component is com.sun.enterprise.web.jsp.JspProbeEmitterImpl
. The event provider defines one event of type jspLoadedEvent
. The signature of the method that is associated with this event is as follows:
void jspLoaded (String jsp, String hostName) <probe-provider moduleProviderName="glassfish" moduleName="web" probeProviderName="jsp"> <probe name="jspLoadedEvent"> <class>com.sun.enterprise.web.jsp.JspProbeEmitterImpl</class> <method>jspLoaded</method> <signature>void (String,String)</signature> <probe-param type="String" name="jsp"/> <probe-param type="String" name="hostName"/> <return-param type="void" /> </probe> </probe-provider>
Packaging a component's event providers enables the monitoring infrastructure of GlassFish Server to discover the event providers automatically.
To package a component's event providers, add an entry to the component's META-INF/MANIFEST.MF
file that identifies all of the component's event providers. The format of the entry depends on how the event providers are defined:
If the event providers are defined as Java classes, the entry is a list of the event providers' class names as follows:
probe-provider-class-names : class-list
The class-list
is a comma-separated list of the fully qualified Java class names of the component's event providers.
If the event providers are defined as XML fragments, the entry is a list of the paths to the files that contain the XML fragments as follows:
probe-provider-xml-file-names : path-list
The path-list
is a comma-separated list of the paths to the XML files relative to the root of the archive in the JAR file.
Example 5-3 Manifest Entry for Event Providers That Are Defined as Java Classes
This example shows the entry in the META-INF/MANIFEST.MF
file of a component whose event provider is the org.glassfish.pluggability.monitoring.ModuleProbeProvider
class.
probe-provider-class-names : org.glassfish.pluggability.monitoring.ModuleProbeProvider
At runtime, your add-on component might perform an operation that generates statistics. To provide statistics about the operation to GlassFish Server, your component must send an event of the correct type when performing the operation.
To send an event, instantiate your event provider class and invoke the method of the event provider class for the type of the event. Instantiate the class and invoke the method in the class that represents your add-on component. 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 instantiating the TxManager
class and invoking the onTxBegin
method to send an event of type begin
. This event indicates that a component is about to begin a transaction.
The TxManager
class is instantiated in the constructor of the TransactionManagerImpl
class. 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.
... public class TransactionManagerImpl { ... public TransactionManagerImpl() { TxManager txProvider = new TxManager(); ... } ... public void begin() { String txId = createTransactionId(); .... txProvider.onTxBegin(txId); //emit } ... }
A monitorable object is a component, subcomponent, or service that can be monitored. GlassFish Server uses a tree structure to track monitorable objects.
Because the tree is dynamic, the tree changes as components of the GlassFish Server instance are added, modified, or removed. Objects are also added to or removed from the tree in response to configuration changes. For example, if monitoring for a component is turned off, the component's monitorable object is removed from the tree.
To enable system administrators to access statistics for all components in the same way, you must provide statistics for an add-on component by updating the monitorable object tree. Statistics for the add-on component are then available through the GlassFish Server administrative commands get
, list
, and set
. These commands locate an object in the tree through the object's dotted name.
For more information about the tree structure of monitorable objects, see "How the Monitoring Tree Structure Works" in Oracle GlassFish Server Administration Guide.
To make an add-on component a monitorable object, you must add the add-on component to the monitorable object tree.
To update the statistics for an add-on component, you must add the statistics to the monitorable object tree, and create event listeners to gather statistics from events that represent these statistics. At runtime, these listeners must update monitorable objects with statistics that these events contain. The events are sent by event provider classes. For information about how to create event provider classes and send events, see Defining Statistics That Are to Be Monitored.
Updating the monitorable object tree involves the following tasks:
An event listener gathers statistics from events that an event provider sends. To enable an add-on component to gather statistics from events, create listeners to receive events from the event provider. The listener can receive events from the add-on component in which the listener is created and from other components.
To create an event listener, write a Java class to represent the listener. The listener can be any Java object.
An event listener also represents a component's statistics. To enable the Application Server Management Extensions (AMX) to expose the statistics to client applications, annotate the declaration of the class with the org.glassfish.gmbal.ManagedObject
annotation.
Ensure that the class that you write meets these requirements:
The return value of all callback methods in the listener must be void.
Because the methods of your event provider class may be entered by multiple threads, the listener must be thread safe.
The listener must have the same restrictions as a Java Platform, Enterprise Edition (Java EE) application. For example, the listener cannot open server sockets, or create threads.
A listener is called in the same thread as the event method. As a result, the listener can use thread locals. If the monitored system allows access to thread locals, the listener can access thread locals of the monitored system.
Note:
A listener that is not registered to listen for events is never called by the framework. Therefore, unregistered listeners do not consume any computing resources, such as memory or processor cycles.
Represent each statistic as the property of a JavaBeans specification getter method of your listener class. Methods in the listener class for processing events can then access the property through the getter method. For more information, see Subscribing to Events From Event Provider Classes.
To enable AMX to expose the statistic to client applications, annotate the declaration of the getter method with the org.glassfish.gmbal.ManagedAttribute
annotation. Set the id
element of the @ManagedAttribute
annotation to the property name all in lowercase.
The data type of the property that represents a statistic must be a class that provides methods for computing the statistic from event data.
The org.glassfish.external.statistics.impl
package provides the following classes to gather and compute statistics data:
AverageRangeStatisticImpl
Provides standard measurements of the lowest and highest values that an attribute has held and the current value of the attribute.
BoundaryStatisticImpl
Provides standard measurements of the upper and lower limits of the value of an attribute.
BoundedRangeStatisticImpl
Aggregates the attributes of RangeStatisticImpl
and BoundaryStatisticImpl
and provides standard measurements of a range that has fixed limits.
CountStatisticImpl
Provides standard count measurements.
RangeStatisticImpl
Provides standard measurements of the lowest and highest values that an attribute has held and the current value of the attribute.
StatisticImpl
Provides performance data.
StringStatisticImpl
Provides a string equivalent of a counter statistic.
TimeStatisticImpl
Provides standard timing measurements.
Example 5-5 Representing a Component's Statistics in an Event Listener Class
This example shows the code for representing the txcount
statistic in the TxListener
class.
... import org.glassfish.external.statistics.CountStatistic; import org.glassfish.external.statistics.impl.CountStatisticImpl; ... import org.glassfish.gmbal.ManagedAttribute; import org.glassfish.gmbal.ManagedObject; ... @ManagedObject public class TxListener { private CountStatisticImpl txCount = new CountStatisticImpl("TxCount", "count", "Number of completed transactions"); ... @ManagedAttribute(id="txcount") public CountStatistic getTxCount(){ return txCount; } }
To receive events from event provider classes, a listener must subscribe to the events. Subscribing to events also specifies the provider and the type of events that the listener will receive.
To subscribe to events from event provider classes, write one method in your listener class to process each type of event. To specify the provider and the type of event, annotate the method with the org.glassfish.external.probe.provider.annotations.ProbeListener
annotation. In the @ProbeListener
annotation, specify the provider and the type as follows:
"module-providername:module-name:probe-provider-name:event-type"
The application to which the event provider belongs. This parameter must be the value of the moduleProviderName
element or attribute in the definition of the event provider. See Defining an Event Provider by Writing a Java Class and Defining an Event Provider by Writing an XML Fragment.
The module for which the event provider is defined. This parameter must match be the value of the moduleName
element or attribute in the definition of the event provider. See Defining an Event Provider by Writing a Java Class and Defining an Event Provider by Writing an XML Fragment.
The name of the event provider. This parameter must match be the value of the probeProviderName
element or attribute in the definition of the event provider. See Defining an Event Provider by Writing a Java Class and Defining an Event Provider by Writing an XML Fragment.
The type of the event. This type is defined in the event provider class. For more information, see Defining Event Types in an Event Provider Class.
Annotate each parameter in the method signature with the @ProbeParam
annotation. Set the value
element of the @ProbeParam
annotation to the name of the parameter.
In the method body, provide the code to update monitoring statistics in response to the event.
Example 5-6 Subscribing to Events From Event Provider Classes
This example shows the code for subscribing to events of type begin
from the tx
component. The provider of the component is TxManager
. The body of the begin
method contains code to increase the transaction count txcount by 1 each time that an event is received.
The definition of the begin
event type is shown in Example 5-1.
The code for sending begin
events is shown in Example 5-4.
The instantiation of the txCount
object is shown in Example 5-5.
... import org.glassfish.external.probe.provider.annotations.ProbeListener; import org.glassfish.external.probe.provider.annotations.ProbeParam; import org.glassfish.gmbal.ManagedObject; ... @ManagedObject public class TxListener { ...; @ProbeListner("examplecomponent:transaction:manager:begin") public void begin( @ProbeParam("{txId}") String txId) { txCount.increment(); } }
Registering an event listener enables the listener to receive callbacks from the GlassFish Server event infrastructure. The listener can then collect data from events and update monitorable objects in the object tree. These monitorable objects form the basis for monitoring statistics.
Registering an event listener also makes a component and its statistics monitorable objects by adding statistics for the component to the monitorable object tree.
At runtime, the GlassFish Server event infrastructure registers listeners for an event provider when the event provider is started and unregisters them when the event provider is shut down. As a result, listeners have no dependencies on other components.
To register a listener, invoke the static org.glassfish.external.probe.provider.StatsProviderManager.register
method in the class that represents your add-on component. In the method invocation, pass the following information as parameters:
The name of the configuration element with which all statistics in the event listener are to be associated. System administrators use this element for enabling or disabling monitoring for the event listener.
The node in the monitorable object tree under which the event listener is to be registered. To specify the node, pass one of the following constants of the org.glassfish.external.probe.provider.PluginPointPluginPoint
enumeration:
To register the listener under the server/applications
node, pass the APPLICATIONS
constant.
To register the listener under the server
node, pass the SERVER
constant.
The path through the monitorable object tree from the node under which the event listener is registered down to the statistics in the event listener. The nodes in this path are separated by the slash (/
) character.
The listener object that you are registering.
Example 5-7 Registering an Event Listener
This example shows the code for registering the event listener TxListener
for the add-on component that is represented by the class TransactionManagerImpl
. The statistics that are defined in this listener are associated with the web-container
configuration element. The listener is registered under the server/applications
node. The path from this node to the statistics in the event listener is tx/txapp
.
Code for the constructor of the TxListener
class is beyond the scope of this example.
... import org.glassfish.external.probe.provider.StatsProviderManager; import org.glassfish.external.probe.provider.PluginPoint ... public class TransactionManagerImpl { ... StatsProviderManager.register("web-container", PluginPoint.APPLICATIONS, "tx/txapp", new TxListener()); ... }
The GlassFish Server administrative subcommands get
, list
, and set
locate a statistic through the dotted name of the statistic. The dotted name of a statistic for an add-on component is determined from the registration of the event listener that defines the statistic as follows:
listener-parent-node.path-to-statistic.statistic-name
The node in the monitorable object tree under which the event listener that defines the statistic is registered. This node is passed in the invocation of the register
method that registers the event listener. For more information, see Registering an Event Listener.
The path through the monitorable object tree from the node under which the event listener is registered down to the statistic in the event listener in which each slash is replaced with a period. This path is passed in the invocation of the register
method that registers the event listener. For more information, see Registering an Event Listener.
The name of the statistic. This name is the value of the id
element of the @ManagedAttribute
annotation on the property that represents the statistic. For more information, see Representing a Component's Statistics in an Event Listener Class.
For example, the dotted name of the txcount
statistic that is defined in Example 5-5 and registered in Example 5-7 is as follows:
server.applications.tx.txapp.txcount
The formats of the URL to a REST resource that represents a statistic is as follows:
http://host:port/monitoring/domain/path
The host where the DAS is running.
The HTTP port or HTTPS port for administration.
The path to the statistic. The path is the dotted name of the attribute in which each dot (.
) is replaced with a slash (/
).
For example, the URL the REST resource for the txcount
statistic that is defined in Example 5-5 and registered in Example 5-7 is as follows:
http://localhost:4848/monitoring/domain/server/applications/tx/txapp/txcount
In this example, the DAS is running on the local host and the HTTP port for administration is 4848.
This example shows a component that monitors the number of requests that a container receives. The following table provides a cross-reference to the listing of each class or interface in the example.
Class or Interface | Listing |
---|---|
|
|
|
|
|
|
|
|
|
Example 5-8 Event Provider Class
This example illustrates how to define an event provider as explained in Defining an Event Provider by Writing a Java Class.
The example shows the definition of the ModuleProbeProvider
class. The event provider sends events when the request count is increased by 1 or decreased by 1.
This class defines the following methods:
moduleCountIncrementEvent
moduleCountDecrementEvent
The name of each method is also the name of the event type that is associated with the method.
A parameter that is named count
is passed to each method.
package org.glassfish.pluggability.monitoring; import org.glassfish.external.probe.provider.annotations.Probe; import org.glassfish.external.probe.provider.annotations.ProbeParam; import org.glassfish.external.probe.provider.annotations.ProbeProvider; /** * Monitoring count events * Provider interface for module specific probe events. * */ @ProbeProvider(moduleProviderName = "glassfish", moduleName = "mybeanmodule", probeProviderName = "mybean") public class ModuleProbeProvider { /** * Emits probe event whenever the count is incremented */ @Probe(name = "moduleCountIncrementEvent") public void moduleCountIncrementEvent( @ProbeParam("count") Integer count) { } /** * Emits probe event whenever the count is decremented */ @Probe(name = "moduleCountDecrementEvent") public void moduleCountDecrementEvent( @ProbeParam("count") Integer count) { } }
This example illustrates how to register an event listener as explained in Registering an Event Listener. The example shows the code for registering an instance of the listener class ModuleStatsTelemetry
. This instance is added as a child of the server/applications
node of the tree.
package org.glassfish.pluggability.monitoring; import org.jvnet.hk2.component.PostConstruct; import org.jvnet.hk2.annotations.Service; import org.jvnet.hk2.annotations.Scoped; import org.jvnet.hk2.component.Singleton; import org.glassfish.external.probe.provider.StatsProviderManager; import org.glassfish.external.probe.provider.PluginPoint; /** * Monitoring Count Example * Bootstrap object for registering probe provider and listener * */ @Service @Scoped(Singleton.class) public class ModuleBootStrap implements PostConstruct { @Override public void postConstruct() { try { StatsProviderManager.register("web-container", PluginPoint.APPLICATIONS, "myapp", new ModuleStatsTelemetry()); } catch (Exception e) { System.out.println("Caught exception in postconstruct"); e.printStackTrace(); } } }
This example shows how to perform the following tasks:
Creating Event Listeners. The example shows the code of the ModuleStatsTelemetry
listener class.
Representing a Component's Statistics in an Event Listener Class. The example shows the code for representing the countmbeancount
statistic.
Subscribing to Events From Event Provider Classes. The example shows the code for subscribing to the following types of events from the count
component:
moduleCountIncrementEvent
moduleCountDecrementEvent
package org.glassfish.pluggability.monitoring; import org.glassfish.external.statistics.CountStatistic; import org.glassfish.external.statistics.impl.CountStatisticImpl; import org.glassfish.external.probe.provider.annotations.ProbeListener; import org.glassfish.external.probe.provider.annotations.ProbeParam; import org.glassfish.gmbal.ManagedAttribute; import org.glassfish.gmbal.ManagedObject; /** * Monitoring counter example * Telemtry object which listens to probe events and updates * the monitoring stats * */ @ManagedObject public class ModuleStatsTelemetry { private CountStatisticImpl countMBeanCount = new CountStatisticImpl( "CountMBeanCount", "count", "Number of MBeans"); @ManagedAttribute(id = "countmbeancount") public CountStatistic getCountMBeanCount() { return countMBeanCount; } @ProbeListener("count:example:countapp:moduleCountIncrementEvent") public void moduleCountIncrementEvent( @ProbeParam("count") Integer count) { countMBeanCount.increment(); } @ProbeListener("count:example:countapp:moduleCountDecrementEvent") public void moduleCountDecrementEvent( @ProbeParam("count") Integer count) { countMBeanCount.decrement(); } }
This example defines the interface for a simple standard MBean that has methods to increase and decrease a counter by 1.
package com.example.count.monitoring; /** * Monitoring counter example * ModuleMBean interface * */ public interface ModuleMBean { public Integer getCount() ; public void incrementCount() ; public void decrementCount() ; }
Example 5-12 MBean Implementation
This example illustrates how to send an event as explained in Sending an Event. The example shows code for sending events as follows:
The moduleCountIncrementEvent
method is invoked in the body of the incrementCount
method.
The moduleCountDecrementEvent
method is invoked in the body of the decrementCount
method.
The methods incrementCount
and decrementCount
are invoked by an entity that is beyond the scope of this example, for example, JConsole.
package org.glassfish.pluggability.monitoring; /** * Monitoring counter example * ModuleMBean implementation * */ public class Module implements ModuleMBean { private int k = 0; private ModuleProbeProvider mpp = null; @Override public Integer getCount() { return k; } @Override public void incrementCount() { k++; if (mpp != null) { mpp.moduleCountIncrementEvent(k); } } @Override public void decrementCount() { k--; if (mpp != null) { mpp.moduleCountDecrementEvent(k); } } void setProbeProvider(ModuleProbeProvider mpp) { this.mpp = mpp; } }