In today's complex e-business environment, customers need to be able to monitor different components of the entire production environment. WebSphere® Application Server, Version 4.0 lets you monitor run time and application components through its Performance Monitoring Infrastructure (PMI) API.
In this article, we will discuss how to use the PMI API to write a performance monitoring tool for WebSphere Application Server. A sample command-line program developed using the PMI API is available for download below. The PMI API documentation is also provided as a separate download.
Performance Monitoring Infrastructure API
The PMI API provides a framework to instrument WebSphere Application Server run-time and application components. The client side of this framework is externalized and published as a lightweight JavaTM API that allows you to gather performance data from the instrumental components. This client-side API is used by WebSphere Resource Analyzer and tool vendors; you can also use it to develop your own custom monitoring tool.
The PMI client uses RMI over IIOP to connect to WebSphere AdminServer. In addition, a performance servlet is provided to return performance data in XML format.
Figure 1 below shows the client-side view of PMI in WebSphere Application Server 4.0 Advanced Edition.
Figure 1. PMI client-side view

While the server side of the PMI API in each application server keeps the performance data as raw counter values, the client side retrieves and manipulates the raw counters to provide more meaningful values, such as average, time-weighted average, percentage, delta, and rate, etc. This minimizes the server overhead and allows the server data to be shared across multiple clients.
PMI API support in different WebSphere Application Server versions:
| WebSphere Application Server Version/Edition | PMI API support |
| WebSphere 4.0.2 Advanced Single Server | Yes, via session bean |
| WebSphere 4.0.1 Advanced | Yes |
| WebSphere 4.0 Advanced Single Server | No |
| WebSphere 3.5.5 Advanced | Yes, via 4.0.2 PMI client mapping |
The performance data from the PMI client is organized into modules. In WebSphere Application Server 4.0, PMI provides performance data about the following modules:
- Connection pool - Database connection pool
- Thread pool - Web container and ORB thread pool
- Session manager - HTTP Servlet sessions
- Transaction manager - Transactions
- JVM run time - Application server JVM
- JVMPI - JVM Profiler Interface data
- J2C - J2C connectors
- EJB module - EJBs and their methods
- Web applications - Servlets and JSPsTM
A module can have sub-modules and each module/sub-module will have related performance data (that is, metric or counter). For instance, the Thread Pool module has two sub-modules: Web Container pool and ORB pool. Each of these sub-modules will have performance data, such as pool size, active threads, etc., and the parent Thread Pool module will aggregate the data from the sub-modules.
Figure 2. PMI Thread Pool module

Each module has an associated instrumentation or monitoring level (Max, High, Medium, Low, None) that defines the data set for a given module. For the Thread Pool module,
- None will disable all {}
- Low will enable {Threads created, Threads destroyed}
- High will enable {Threads created, Threads destroyed, Active threads, Pool size, Percent maxed}
The instrumentation level for each module can be set to a desired level (described in Step 2 below). Each metric in a module has a predefined level. A metric will be enabled if the module level is equal to or higher than its level. In the above example, the Pool Size is at level High and Threads created is at level Low.
Note: WebSphere Application Server nodes and servers are represented as modules without any performance data.
The client-side PMI classes are defined in the com.ibm.websphere.pmi
package. The following are some of the core client-side classes that
will be used in developing a custom monitoring tool. Refer to the PMI API documentation
for detailed information about the following and other available classes.
| Class | Description |
| com.ibm.websphere.pmi.CpdCollection | Represents a module or sub-module. For example, Thread Pool will be a CpdCollection object with two sub-collections: one for Web Container pool and another one for ORB pool. |
| com.ibm.websphere.pmi.CpdData | Represents performance data. For example, Pool Size will be CpdData object available within Thread pool CpdCollection. |
| com.ibm.websphere.pmi.CpdValue | Represents the actual numeric value of the counter. CpdStat and CpdLoad are specialized CpdValue representing Average and Time-weighted average. |
| com.ibm.websphere.pmi.PerfDescriptor | Identifies a module (CpdCollection) or individual counter
(CpdData). PerfDescriptor has Node, Server, Module and a fully qualified
name.
For instance, the fully qualified name of Web container
thread pool module can be:
|
| com.ibm.websphere.pmi.PmiClient | This is the main client-side interface to the server side PMI and has methods to connect, query and get performance data from the WebSphere AdminServer. |
Figure 3 below shows the relationship among the above classes.
Figure 3. PMI client-core classes

A step-by-step look at using PMI
With this basic understanding of the core PMI client classes, let's look at the steps involved in gathering performance data.
Step 1: Identifying PMI modules
The first step is to connect to the WebSphere AdminServer and find out which nodes, application servers and modules are available for monitoring. The following code snippet will help you identify all of the above.
// Connect to WebSphere AdminServer running at hostName:900
PmiClient pmiClient = new PmiClient ("hostName", 900);
// Get Node PerfDescriptor
PerfDescriptor[] nodePd = pmiClient.listNodes ();
// Get first node name
String nodeName = nodePd[0].getName();
// Get AppServer PerfDescriptor
PerfDescriptor[] serverPd = pmiClient.listServers (nodeName);
// Get all modules in first application server
PerfDescriptor[] modulePd = pmiClient.listMembers(serverPd[0]); |
Now, we have a PerfDescriptor for all of the modules in the first application server. The listMembers call can be recursively made to get the sub-modules, and so on.
This is just one way to navigate down to the modules. PMI provides a rich set of API and allows you to gather data in different ways depending on your application need. For instance, you can construct a PerfDescriptor and query the server if you know the PMI data hierarchy for the server.
Step 2: Setting instrumentation level
The next step is to enable the modules for monitoring (default setting is disabled). Each module has an instrumentation level (max, high, medium, low, or none) that determines the number of counters available for monitoring. This setting is stored and used by the application server and not by the PMI client. Therefore, this setting is common across all the clients and if one client changes the setting, it will affect all the other clients.
The instrumentation level can be set using the WebSphere Application Server Administrative Console or WebSphere Resource Analyzer. The following code illustrates how to get and set the instrumentation level using the PMI API.
The getInstrumentationLevel() returns the instrumentation
level for all of the modules and sub-modules recursively in the given node and
server.
// Get instrumentation level
PerfLevelSpec[] level =
pmiClient.getInstrumentationLevel (nodeName, serverName);
// Get module path
String[] modulePath = level[i].getPath();
//ex: path for Thread pool module is {pmi, threadPoolModule}
// Get level
int instruLevel = level[i].getLevel();
// ex: levels defined in PmiConstants.java |
Now, you can navigate this level array, change the level to
the desired level, and call setInstrumentationLevel() to set the
level.
// To set ThreadPool module and sub-modules to high boolean recursiveFlag = true; level[i].setLevel (PmiConstants.LEVEL_HIGH); pmiClient.setInstrumentationLevel (nodeName, serverName, level, recursiveFlag); |
Alternatively, to set the level for a known module or an individual
module (without calling the getInstrumentationLevel() method),
you can do the following:
PerfLevelSpec[] spec = new PerfLevelSpec [1];
String[] modulePath = new String[] {"threadPoolModule"}
spec[0] = pmiClient.createPerfLevelSpec
(modulePath, PmiConstants.LEVEL_HIGH);
pmiClient.setInstrumentationLevel
(nodeName, serverName, spec, recursiveFlag); |
The changes made through setInstrumentationLevel will take effect immediately (without having to restart the server) and will be persistent.
Note that all levels may not be applicable to a given module. For instance, the JVM module has three counters and all three gets turned on when the level is set to Low. In this case, setting it to a level higher than Low will still give only these three counters. The Max level is used in an EJB module to turn on method-level monitoring.
The instrumentation level also represents the performance cost involved in collecting the data. PMI is designed to be a low cost framework, so it can be used in production monitoring. When tested in our labs, we found the following:
- With all modules set to High: ~2% performance degradation
- With all modules set to Max: ~5% performance degradation
Once the instrumentation level is set for a given module, getting the performance data is just a single method call. You can send one or multiple PerfDescriptors and get their corresponding CpdCollection objects as follows:
// Get all sub-modules recursively Boolean recursiveFlag = true; // Get performance data for ONE module CpdCollection col = pmiClient.get (modulePd[0], recursiveFlag); // Or, get performance data for ALL of the modules CpdCollection[] col = pmiClient.gets (modulePd, recursiveFlag); |
Step 4: Navigating the performance data set (CpdCollection)
Now, let's navigate the CpdCollection to get individual performance data:
// Get the performance data set from a CpdCollection CpdData[] perfData = col.dataMembers(); // Get the sub-modules CpdCollection[] subPerfData = col.subcollections (); |
As mentioned earlier, a PerfDescriptor identifies a CpdData. So, from the PerfDescriptor we can get the name of the data as follows:
perfData[0].getDescriptor().getName(); //e.g. threadPoolModule.threadCreates |
or
perfData[0].getDescriptor().getFullName(); // e.g. root/flow/DefaultServer/threadPoolModule/ threadPoolModule.threadCreates |
Finally, let's get to the actual counter value itself:
// Get the counter value CpdValue value = perfData[0].getValue (); // Refer to Step 5 for the definition of returned double value double numOfThreadsCreated = value.getValue(); long timeInMillis = value.getTime(); |
The timeInMillis represents the time associated with the counter value.
Step 5: Determining performance data types
The counter value from CpdData can be one of the following three types:
| Type | Description | Class | Methods |
| Numeric | Simple numeric counter,for example, threads created | CpdValue | getValue() - returns numeric count |
| Statistic | Average value of the counter, for example, average response time | CpdStat | getValue() - returns mean
count() - returns number of samples |
| Load | Time-weighted average, for example, pool size | CpdLoad | getValue() - returns current value
mean() - returns time-weighted average |
The counter type can be determined as follows:
CpdValue value = perfData[0].getValue ();
// Counter type
int counterType = value.getType();
if (counterType == PmiConstants.TYPE_STAT)
{
}
else
if (CounterType == PmiConstants.TYPE_LOAD)
{
}
else
{
// Numeric Type
} |
After finding the counter type, you can call the appropriate methods to get the counter value and their components, if any, such as mean, weight, etc.
An in-depth look at PMI features
So far, we have seen how to get the basic performance data from WebSphere Application Server using the PMI API. Now, let's take an in-depth look at some of the PMI features.
Each time we query PmiClient using a PerfDescriptor, we get a new CpdCollection object. Instead of dealing with a new CpdCollection object each time, we can update the existing one with the new collection as follows:
// Original collection CpdCollection orgCol = pmiClient.get (modulePd) // Updating the original collection with new collection orgCol.update (pmiClient.get (modulePd)); |
This is equivalent to establishing a base value and then updating the base with a new value. This model can be used to create a snapshot view (this is explained in the next feature item). By default, the update method updates all of the sub-collections recursively and will remove any collection (from the base) that is not present in the new collection. The default behavior can be altered by using the following methods:
update (CpdCollection newCol, Boolean keepOld); update (CpdCollection newCol, Boolean keepOld, Boolean, recursiveFlag); |
Also, the update() on CpdCollection will generate
events (CpdEvent) to indicate the changes made in the original collection, for
example, new data, new sub-module, etc. By implementing the CpdEventListener
interface, you can receive all of these events. This feature will be particularly
useful when developing a GUI application using PMI. Note that the events can
be sent only to listeners in the local JVM process.
The application server keeps the cumulative raw counter value from the time it was started. The data in the client side can be reset to capture a snapshot view.
Here is an example to find the number of requests processed between the interval t2 and t3.
Let's assume the following sample data:
| Time | Server value (total req processed) | Client value (without any reset) | Client value (reset at t2) |
| t0 | 0 | 0 | 0 |
| t1 | 100 | 100 | 100 |
| t2 | 180 | 180 | 180 resets to 0 |
| t3 | 250 | 250 | 70 |
| t4 | 300 | 300 | 120 |
From the above sample data, the number of requests processed between the interval {t2 to t3} is 70 and {t2 and t4} is 120.
This can be computed programmatically by maintaining a base
CpdCollection and updating it as described in the previous feature. For example,
to count the number of requests between t2 and t3, call the reset()
method on the CpdCollection (or the CpdData) at t2. At t3, get data from the
server and update the base CpdCollection. Now, the data in the base collection
will represent a snapshot from t2 to t3.
Static information about performance data
We have seen how to get the dynamic side (actual counter) of the performance data. The static information, such as counter name, description, level, etc., can be obtained from the PmiDataInfo class.
PmiDataInfo can be obtained in two ways, as shown below.
Getting PmiDataInfo from a CpdData instance:
// CpdData[] perfData; PmiDataInfo staticInfo = perfData[0].getPmiDataInfo (); staticInfo.getName(); staticInfo.getLevel (); staticInfo.getComment(); |
Getting PmiDataInfo from PmiModuleConfig:
// Get config for all modules PmiModuleConfig[] configs = PmiClient.getConfigs(); // Locate a module String modName = configs[0].getShortName (); // ex: "threadPoolModule" // List the dataset in the given module config PmiDataInfo[] staticInfo = configs[0].listAllData (); |
Connecting remotely through a firewall
Since PmiClient uses RMI/IIOP to connect to the WebSphere AdminServer, you need to "poke a hole" in the firewall to connect to a server behind the firewall. Or, you can use the performance servlet to collect the data.
When the WebSphere Application Server security is turned ON,
the user needs to be authenticated before calling any PMI API. You can configure
the %WAS_HOME%\properties\sas.client.props to choose the appropriate
login source.
Refer to the WebSphere 4.0 InfoCenter for details on different security configurations.
WebSphere Resource Analyzer and the performance servlet
WebSphere Resource Analyzer, a default PMI data viewer, is shipped with WebSphere Application Server 4.0 Advanced Edition. It uses PMI API and provides a simple GUI to monitor, record, and replay performance data.
The performance servlet (PerfServlet), a firewall-friendly
PMI data viewer, is also shipped with WebSphere Application Server 4.0 Advanced
Edition (%WAS_HOME%\installableApps\perfServletApp.ear). Install
this EAR file in any one of the application servers in a node, and invoke it
with this URL: http://localhost/wasPerfTool/servlet/perfservlet. PerfServlet
provides performance data in the XML format.
WebSphere Statistic (wsstat): A sample program
The WebSphere Statistic tool is a command-line performance monitoring tool developed using PMI. When invoked, it lists all of the modules that are available for monitoring. It allows you to monitor one module at a time, with a given refresh interval and can record the data to a file, if required.
The source code is available here. Figure 4 below shows screen shot of the wsstat tool.
Figure 4. The WebSphere Statistic tool

WebSphere PMI API lets you gather performance data from WebSphere Application Server. PMI API can be used to build custom tools to monitor WebSphere Application Server in the production environment.
| Name | Size | Download method |
|---|---|---|
| download.zip | 92 KB | FTP |
Information about download methods
- Performance monitoring infrastructure client package documentation in
WebSphere
Advanced Edition InfoCenter, Chapter Tuning, Section 9.2.
Srini Rangaswamy is an advisory engineer at IBM. He is a member of the WebSphere performance group and is responsible for WebSphere Resource Analyzer. You can reach Srini at sriniri@us.ibm.com.
Ruth Willenborg is a senior engineer at IBM. She has 15 years of experience in software development and is currently a member of the WebSphere development organization. Ruth is responsible for WebSphere's performance monitoring and performance benchmarking initiatives. You can reach Ruth at rewillen@us.ibm.com.
Wenjian Qiao is an advisory engineer at IBM. She is a member of the WebSphere performance group and is responsible for the design and implementation of WebSphere's Performance Monitoring Infrastructure. You can reach Wenjian at wenjian@us.ibm.com.
Comments (Undergoing maintenance)





