Contents


Retrieve performance metrics from the WebSphere Liberty profile, Part 2

Data collection by using Jython

Comments

Content series:

This content is part # of # in the series: Retrieve performance metrics from the WebSphere Liberty profile, Part 2

Stay tuned for additional content in this series.

This content is part of the series:Retrieve performance metrics from the WebSphere Liberty profile, Part 2

Stay tuned for additional content in this series.

The IBM WebSphere Liberty profile provides performance metrics by using the monitor feature, which conforms to the Java® Management Extension (JMX) standard. This tutorial explains how to use Jython scripts to retrieve these metrics by using the REST Connector API to connect to a Liberty server or Liberty collective controller. In this part, you collect the data by using Jython scripts.

Copy the REST Connector API to the Jython directory

In this tutorial, you use the REST Connector API that is available with the Liberty profile to connect, by using JMX, to the member and controller Liberty servers and to collect performance data. This remote access to the REST connector requires an administrator role and Secure Sockets Layer (SSL) to ensure the confidentiality of data exchanges.

By default, the webProfile loads all features that are needed, including the restConnector-1.0 and ssl-1.0 features. You need only to add the monitor feature. The administrator role is configured with the <quickStartSecurity userName="wlpadmin" userPassword="wlpadmin"/> tag.

Copy the REST connector files to the Jython directories:

$ cd $WLP_DIR/wlp/jython
$ cp $WLP_DIR/wlp/clients/jython/restConnector.py  .
$ cp $WLP_DIR/wlp/clients/restConnector.jar .
$ ls -l

Listing 1 shows the REST connector files that are copied.

Listing 1. Copying the REST connector files
-rwxr-xr-x 1 usr grp 37021723 Oct 13 16:11 jython-standalone-2.7.0.jar
-rw-r--r-x 1 usr grp 223484 Oct 14 12:15 restConnector.jar
-rwxr-xr-x 1 usr grp 2834 Oct 14 12:14 restConnector.py

Collect the performance data of the Liberty server

Collecting the performance data involves the following steps:

  1. Start a Jython session.
  2. Connect to the controller server.
  3. Connect to the controller MBean server.
  4. List the available MBeans.
  5. For the selected MBeans:
    1. List the available attributes and methods:
      • Jython: dir(), type()
      • Java: getClass(), getMethods()
    2. By using the MBean server connection object, use the methods from the MBean with the parameters and the signature as needed:
      mconnection.invoke( <MBean>, '<method>', ['<param1>', ...],
      ['<param1 type>', ...])

The following sections break down each of these steps.

Start a Jython session

Start an interactive Jython session:

$ java -cp jython-standalone-2.7.0.jar:restConnector.jar org.python.util.jython

Listing 2 shows the results of starting the Jython session.

Listing 2. Starting a Jython session
Jython 2.7.0 (default:9987c746f838, Apr 29 2015, 02:25:11)
[IBM J9 VM (IBM Corporation)] on java1.8.0
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__']

Connect to the controller server

To connect to the controller server, use the JMXRESTConnector object in the restConnector.py file. The following elements are used as shown in Listing 3:

  • Controller truststore key file
  • Controller truststore password
  • Controller host name or IP address
  • Controller port
  • Controller user ID and password
Listing 3. Connecting to the controller server
>>> from restConnector import JMXRESTConnector

>>> JMXRESTConnector.trustStore = '../usr/servers/controller/resources/security/key.jks'
>>> JMXRESTConnector.trustStorePassword = 'wlpadmin'
>>> connector = JMXRESTConnector()
>>> connection = connector.connect( '<controller_hostname>', 9443, 'wlpadmin', 'wlpadmin')
Connecting to the server...
Successfully connected to the server "<controller_hostname>:9443"

Connect to the controller MBean server

Connect to the controller MBean server:

mconnection = connection.getMBeanServerConnection()

Listing 4 shows how to connect to the MBean server and get information about the connection.

Listing 4. Connecting to the controller MBean server
>>> mconnection = connector.getMBeanServerConnection()

>>> mconnection
com.ibm.ws.jmx.connector.client.rest.internal.RESTMBeanServerConnection@aba685fb

>>> dir( mconnection)
['MBeanCount', 'PollingMode', 'ServerPollingThread', '__class__', '__copy__',
 '__deepcopy__', '__delattr__', '__doc__', '__ensure_finalizer__', '__eq__',
 '__format__', '__getattribute__', '__hash__', '__init__', '__ne__', '__new__',
 '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__subclasshook__',
 '__unicode__', 'addNotificationListener', 'class', 'createMBean', 'defaultDomain',
 'domains', 'equals', 'getAttribute', 'getAttributes', 'getClass', 'getDefaultDomain',
 'getDomains', 'getMBeanCount', 'getMBeanInfo', 'getObjectInstance', 'hashCode',
 'invoke', 'isInstanceOf', 'isRegistered', 'notify', 'notifyAll', 'queryMBeans',
 'queryNames', 'removeNotificationListener', 'setAttribute', 'setAttributes', 'toString',
 'unregisterMBean', 'wait']

>>> type( mconnection)
<type 'com.ibm.ws.jmx.connector.client.rest.internal.RESTMBeanServerConnection'>

>>> mconnection.getClass()
<type 'com.ibm.ws.jmx.connector.client.rest.internal.RESTMBeanServerConnection'>

>>> for i in mconnection.getClass().getMethods(): print i
...
public boolean java.lang.Object.equals(java.lang.Object)
public int java.lang.Object.hashCode()
public java.lang.String java.lang.Object.toString()
…
public java.util.Set com.ibm.ws.jmx.connector.client.rest.internal.RESTMBeanServerConnection.queryMBeans(javax
.management.ObjectName,javax.management.QueryExp) throws java.io.IOException
public java.util.Set com.ibm.ws.jmx.connector.client.rest.internal.RESTMBeanServerConnection.queryNames(javax.management.ObjectName,javax.management.QueryExp) throws java.io.IOException
public boolean com.ibm.ws.jmx.connector.client.rest.internal.RESTMBeanServerConnection.isRegistered(java
x.management.ObjectName) throws java.io.IOException
...

List the available MBeans

By using the instropection methods that are available with Jython (type, dir) or Java (getClass, getMethods), you can see the different attributes and methods that are available for all the objects. You can also see the parameters to pass to the methods (the signature).

To list the available MBeans, use the commands in Listing 5. To list all the MBeans, use the queryNames method. To use this method, pass an ObjectName and a QueryExp (set to None) to the method. The syntax for the ObjectName is the standard JMX object name syntax:

domain:key=value,key=value,key=value,...

IBM WebSphere has the following domain:

WebSphere:key=value,key=value,key=value,...
Listing 5. List of the available MBeans
>>> from javax.management import ObjectName

>>> mbeans = mconnection.queryNames( ObjectName( "WebSphere:*"), None).toArray()

>>> type( mbeans)
<type 'array.array'>

>>> mbeans[0]
WebSphere:name=com.ibm.websphere.config.mbeans.FeatureListMBean

>>> type( mbeans[0])
<type 'javax.management.ObjectName'>

>>> for i in mbeans: print i
...
WebSphere:name=com.ibm.websphere.config.mbeans.FeatureListMBean
WebSphere:feature=collectiveController,type=ControllerConfig,name=ControllerConfig
WebSphere:name=com.ibm.websphere.config.mbeans.ServerXMLConfigurationMBean
WebSphere:type=ServletStats,name=com.ibm.ws.jmx.connector.server.rest.MBeanServerConnector
WebSphere:feature=collectiveController,type=CollectiveRepository,name=CollectiveRepository
WebSphere:feature=collectiveController,type=MaintenanceMode,name=MaintenanceMode
WebSphere:feature=collectiveMember,type=EndpointRoutingInfo,name=EndpointRoutingInfo
WebSphere:feature=collectiveController,type=RepositoryPathUtility,
name=RepositoryPathUtility
WebSphere:name=com.ibm.ws.jmx.mbeans.sessionManagerMBean
WebSphere:name=com.ibm.ws.jmx.mbeans.generatePluginConfig
WebSphere:feature=restConnector,type=FileService,name=FileService
WebSphere:feature=collectiveController,type=ServerCommands,name=ServerCommands
WebSphere:name=com.ibm.ws.config.serverSchemaGenerator
WebSphere:feature=collectiveController,type=CollectiveRegistration,
name=CollectiveRegistration
WebSphere:feature=CacheAdmin,type=DynaCache,name=DistributedMap
WebSphere:feature=collectiveController,type=RoutingContext,name=RoutingContext
WebSphere:feature=collectiveController,type=ClusterManager,name=ClusterManager
WebSphere:feature=collectiveController,type=RoutingInfoManager,name=RoutingInfoManager
WebSphere:feature=collectiveController,type=RepositoryConfiguration,
name=RepositoryConfiguration
WebSphere:service=com.ibm.ws.kernel.filemonitor.FileNotificationMBean
WebSphere:feature=channelfw,type=endpoint,name=defaultHttpEndpoint
WebSphere:type=JvmStats
WebSphere:feature=channelfw,type=endpoint,name=defaultHttpEndpoint-ssl
WebSphere:name=com.ibm.websphere.runtime.update.RuntimeUpdateNotificationMBean
WebSphere:feature=collectiveController,type=AdminMetadataManager,name=AdminMetadataManager
WebSphere:feature=collectiveMember,type=SingletonServiceMessenger,
name=SingletonServiceMessenger
WebSphere:feature=kernel,name=ServerInfo
WebSphere:type=ThreadPoolStats,name=Default Executor
WebSphere:feature=restConnector,type=FileTransfer,name=FileTransfer

Get the JvmStats MBean as shown in Listing 6.

Listing 6. Getting the JvmStats MBean
>>> mbeans = mconnection.queryNames( ObjectName( "WebSphere:type=JvmStats,*"),
 None).toArray()

>>> for i in mbeans: print i
...
WebSphere:type=JvmStats

Then, by using the getMBeanInfo method, you can view the details of the JvmStats MBean as shown in Listing 7.

Listing 7. Accessing the JvmStats MBean details
>>> mbean_jvm = mbeans[ 0]
>>> mbean_info = mconnection.getMBeanInfo( mbean_jvm)

>>> type( mbean_info)
<type 'javax.management.MBeanInfo'>

>>> dir( mbean_info)
['__class__', '__copy__', '__deepcopy__', '__delattr__', '__doc__',
 '__ensure_finalizer__', '__eq__', '__format__', '__getattribute__', '__hash__',
 '__init__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
 '__setattr__', '__str__', '__subclasshook__', '__unicode__', 'attributes', 'class',
 'className', 'clone', 'constructors', 'description', 'descriptor', 'equals',
 'getAttributes', 'getClass', 'getClassName', 'getConstructors', 'getDescription',
 'getDescriptor', 'getNotifications', 'getOperations', 'hashCode', 'notifications',
 'notify', 'notifyAll', 'operations', 'toString', 'wait']

>>> mbean_info
javax.management.MBeanInfo[description=Information on the management interface of the
 MBean, attributes=[javax.management.MBeanAttributeInfo[description=UsedMemory,
 name=UsedMemory, type=long, read-only,
 descriptor={openType=javax.management.openmbean.SimpleType(name=java.lang.Long),
 originalType=long}], javax.management.MBeanAttributeInfo[description=FreeMemory,
 name=FreeMemory, type=long, read-only,
 descriptor={openType=javax.management.openmbean.SimpleType(name=java.lang.Long),
 originalType=long}], javax.management.MBeanAttributeInfo[description=Heap, name=Heap,
 type=long, read-only,
 descriptor={openType=javax.management.openmbean.SimpleType(name=java.lang.Long),
 originalType=long}], javax.management.MBeanAttributeInfo[description=UpTime,
 name=UpTime, type=long, read-only,
 descriptor={openType=javax.management.openmbean.SimpleType(name=java.lang.Long),
 originalType=long}], javax.management.MBeanAttributeInfo[description=ProcessCPU,
 name=ProcessCPU, type=double, read-only,
 descriptor={openType=javax.management.openmbean.SimpleType(name=java.lang.Double),
 originalType=double}], javax.management.MBeanAttributeInfo[description=GcCount,
 name=GcCount, type=long, read-only,
 descriptor={openType=javax.management.openmbean.SimpleType(name=java.lang.Long),
 originalType=long}], javax.management.MBeanAttributeInfo[description=GcTime,
 name=GcTime, type=long, read-only,
 descriptor={openType=javax.management.openmbean.SimpleType(name=java.lang.Long),
 originalType=long}]],
 constructors=[javax.management.MBeanConstructorInfo[description=Public constructor of
 the MBean, name=com.ibm.ws.monitors.helper.JvmStats,
 signature=[javax.management.MBeanParameterInfo[description=, name=p1,
 type=com.ibm.ws.monitors.helper.JvmMonitorHelper, descriptor={}]], descriptor={}]],
 operations=[], notifications=[], descriptor={immutableInfo=true,
 interfaceClassName=com.ibm.websphere.monitor.meters.JvmMXBean, mxbean=true}]

To get the attributes of the JvmStats MBean, you use the mbean_info.getAttributes and the MBean server getAttribute methods as shown in Listing 8.

Listing 8. Getting the JvmStats MBean attributes
>>> mbean_attributes = mbean_info.getAttributes()

>>> type( mbean_attributes)
<type 'array.array'>

>>> type( mbean_attributes[ 0])
<type 'javax.management.MBeanAttributeInfo'>

>>> dir( mbean_attributes[0])
['__class__', '__copy__', '__deepcopy__', '__delattr__', '__doc__',
 '__ensure_finalizer__', '__eq__', '__format__', '__getattribute__', '__hash__',
 '__init__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
 '__setattr__', '__str__', '__subclasshook__', '__unicode__', 'class', 'clone',
 'description', 'descriptor', 'equals', 'getClass', 'getDescription', 'getDescriptor',
 'getName', 'getType', 'hashCode', 'is', 'isIs', 'isReadable', 'isWritable', 'name',
 'notify', 'notifyAll', 'readable', 'toString', 'type', 'wait', 'writable']

>>> for attribute in mbean_attributes:
  name = attribute.getName()
  value = mconnection.getAttribute( mbean_jvm, name)
  type = attribute.getType()
  print "      %s [%s] = %s" % ( name, type, str( value))
...
      UsedMemory [long] = 52011592
      FreeMemory [long] = 3481008
      Heap [long] = 55771136
      UpTime [long] = 2435005
      ProcessCPU [double] = 0.0729284201396
      GcCount [long] = 144
      GcTime [long] = 365

>>> exit()

You just collected the Performance Monitoring Infrastructure (PMI) data by using a Jython interactive session. Next, you add Jython utility functions to simplify the process.

Add the Jython utility functions

To facilitate the Jython session, you can create a connection parameter file and some utility functions.

To create the connection parameter file, enter:

$ vi wlp_collect_conf.py

Listing 9 shows the contents of the file, where you must replace the <controller_hostname> variable with the host name of your controller.

Listing 9. The wlp_collect_conf.py connection parameter file
Config = {
                 'host': '<controller_hostname>',
                 'port': 9443,
                 'user': 'wlpadmin',
             'password': 'wlpadmin',
           'truststore': '../usr/servers/controller/resources/security/key.jks',
  'truststore_password': 'wlpadmin',
           'objectName': 'WebSphere:*',
       'collectiveName': 'WebSphere:type=CollectiveRepository,*',
          'routingName': 'WebSphere:type=RoutingContext,*',        
        'attributeName': '*'
}

Now, create the file that contains the functions for the connect, disconnect, and collect utilities:

$ vi wlp_collect.py

The collect function uses the MBean getAttributes and getOperations methods.

The contents of the file must be the same as shown in Listing 10. In this file, you must replace the <controller_hostname> variable with the host name for your controller.

Listing 10. The wlp_collect.py utility functions file
import sys
from restConnector import JMXRESTConnector
from javax.management import ObjectName
from wlp_collect_conf import Config

def connect():
  """
    param : none BUT uses the Config object define in wlp_collect_conf.py
    result: return a connection object
    note  : use simple connect method
  """
  print Config[ 'port']
  print Config[ 'truststore']
  JMXRESTConnector.trustStore = Config['truststore']
  JMXRESTConnector.trustStorePassword = Config[ 'truststore_password']
  connector = JMXRESTConnector()
  connector.connect( Config[ 'host'], Config[ 'port'], Config[ 'user'],
                     Config[ 'password'])
  return connector

def disconnect( connector):
  """
    param : a connection object (return by connect())
    result: none
  """
  connector.disconnect()

def collect( connector, details = False, objectName = Config[ 'objectName'], attributeName = Config[ 'attributeName']):
  """
    param1: connection object (return by connect() function)
    param2: output with or without details (True|False)
    param3: mbean object like "WebSphere:type=JvmStats,*"
    param4: attribute to retrieve in the mbean object
    result: return an array of mbeans objects found
  """
  mconnection = connector.getMBeanServerConnection()
  # print dir( mconnection)
  # "WebSphere:type=endpoint,*"
  mbeans = mconnection.queryNames( ObjectName( objectName), None).toArray()
  for mbean in mbeans:
    print "\n MBean details for %s" % str( mbean)
    # --- get MBeanInfo
    mbean_info = mconnection.getMBeanInfo( mbean)
    mbean_class = mbean_info.className
    # --- printing attributes
    mbean_attributes = mbean_info.getAttributes()
    print "\n   %s attributes" % str( len( mbean_info.attributes))
    for attribute in mbean_attributes:
      name = attribute.name
      value = mconnection.getAttribute( mbean, name)
      type = attribute.type
      if details and (attributeName == "*" or attributeName == name):
        print "      %s [%s] = %s" % ( name, type, str( value))
    # --- printing operations
    mbean_operations = mbean_info.getOperations()
    print "\n   %s operations" % str( len( mbean_info.operations))
    for operation in mbean_operations:
      name = operation.getName()
      # value = mconnection.getOperation( mbean, name)
      # type = operation.type
      if details and (attributeName == "*" or attributeName == name):
        # print "      %s" % name
        print("\n      " + str( operation.getName()) + " : " +
          str( operation.getDescription()))
        for param in operation.getSignature():
          print("        " + str( param.getName()) + " [" +
            str( param.getType()) + "] : " + str( param.getDescription()))
  return mbeans

The collect method can have 1 ̶ 4 parameters:

  • Parameter 1: The connection object
  • Parameter 2: Show details [False, True] (The default is False.)
  • Parameter 3: The ObjectName (The default is WebSphere:*.)
  • Parameter 4: The attribute to collect (The default is *.)

To use the functions of the new utilities, start a Jython session:

$ java -cp jython-standalone-2.7.0.jar:restConnector.jar org.python.util.jython

Listing 11 shows how to use the new utility functions.

Listing 11. Using the utility functions
>>> from wlp_collect import *

>>> dir()
['ClientProvider', 'Config', 'ConnectorSettings', 'JMXConnector', 'JMXRESTConnector', 'ObjectName', '__builtins__', '__doc__', '__name__', '__package__', 'array', 'collect', 'collect_controller', 'connect', 'connect_adv', 'disconnect', 'getServersFromRepository', 'java', 'print_usage', 'script_name', 'sys', 'urllib2']

>>> connection = connect()
9443
../usr/servers/controller/resources/security/key.jks
Connecting to the server...
Successfully connected to the server "<controller_hostname>:9443"

>>> collect( connection, False, "WebSphere:type=JvmStats,*")

 MBean details for WebSphere:type=JvmStats

   7 attributes

   0 operations
array(java.lang.Object, [WebSphere:type=JvmStats])

>>> collect( connection, True,  "WebSphere:type=JvmStats,*")

 MBean details for WebSphere:type=JvmStats

   7 attributes
      UsedMemory [long] = 50492936
      FreeMemory [long] = 11909624
      Heap [long] = 62586880
      UpTime [long] = 7060539
      ProcessCPU [double] = 0.131003185929
      GcCount [long] = 193
      GcTime [long] = 460

   0 operations
array(java.lang.Object, [WebSphere:type=JvmStats])

>>> collect( connection, True,  "WebSphere:type=JvmStats,*", 'FreeMemory')

 MBean details for WebSphere:type=JvmStats

   7 attributes
      FreeMemory [long] = 23083576

   0 operations
array(java.lang.Object, [WebSphere:type=JvmStats])

>>> disconnect( connection)

You have now collected the performance data by connecting to the target Liberty profile server and using the utility functions.

Collect the performance data of the Liberty members that are attached to the collective controller

Next, you collect the performance data of any Liberty member that is attached to the collective controller by connecting only to the controller. You use two MBeans:

  • CollectiveRepository to list the available members
  • RoutingContext to select the member to reach

List the members of the collective by using the collectiveRepository MBean

The controller maintains a repository of the attached Liberty server members. This repository has a tree structure that starts at the root element (/). You can browse this repository by using Jython. Listing 12 shows how to obtain the collectiveRepository MBean and lists all its methods.

Listing 12. The collectiveRepository attributes and methods
>>> connection = connect()
9443
../usr/servers/controller/resources/security/key.jks
Connecting to the server...
Successfully connected to the server "<controller_hostname>:9443"

>>> mbeans = collect( connection)
 MBean details for WebSphere:name=com.ibm.websphere.config.mbeans.FeatureListMBean

   0 attributes

   1 operations

 MBean details for WebSphere:feature=collectiveController,type=ControllerConfig,name=ControllerConfig

   0 attributes

   3 operations
…

>>> for i in mbeans: print i
...
WebSphere:name=com.ibm.websphere.config.mbeans.FeatureListMBean
WebSphere:feature=collectiveController,type=ControllerConfig,name=ControllerConfig
WebSphere:name=com.ibm.websphere.config.mbeans.ServerXMLConfigurationMBean
WebSphere:type=ServletStats,name=com.ibm.ws.jmx.connector.server.rest.MBeanServerConnector
WebSphere:feature=collectiveController,type=CollectiveRepository,name=CollectiveRepository
WebSphere:feature=collectiveController,type=MaintenanceMode,name=MaintenanceMode
WebSphere:feature=collectiveMember,type=EndpointRoutingInfo,name=EndpointRoutingInfo
WebSphere:feature=collectiveController,type=RepositoryPathUtility,
name=RepositoryPathUtility
WebSphere:name=com.ibm.ws.jmx.mbeans.sessionManagerMBean
WebSphere:name=com.ibm.ws.jmx.mbeans.generatePluginConfig
WebSphere:feature=restConnector,type=FileService,name=FileService
WebSphere:feature=collectiveController,type=ServerCommands,name=ServerCommands
WebSphere:name=com.ibm.ws.config.serverSchemaGenerator
WebSphere:feature=collectiveController,type=CollectiveRegistration,
name=CollectiveRegistration
WebSphere:feature=CacheAdmin,type=DynaCache,name=DistributedMap
WebSphere:feature=collectiveController,type=RoutingContext,name=RoutingContext
WebSphere:feature=collectiveController,type=ClusterManager,name=ClusterManager
WebSphere:feature=collectiveController,type=RoutingInfoManager,name=RoutingInfoManager
WebSphere:feature=collectiveController,type=RepositoryConfiguration,
name=RepositoryConfiguration
WebSphere:service=com.ibm.ws.kernel.filemonitor.FileNotificationMBean
WebSphere:feature=channelfw,type=endpoint,name=defaultHttpEndpoint
WebSphere:type=JvmStats
WebSphere:feature=channelfw,type=endpoint,name=defaultHttpEndpoint-ssl
WebSphere:name=com.ibm.websphere.runtime.update.RuntimeUpdateNotificationMBean
WebSphere:feature=collectiveController,type=AdminMetadataManager,name=AdminMetadataManager
WebSphere:feature=collectiveMember,type=SingletonServiceMessenger,
name=SingletonServiceMessenger
WebSphere:feature=kernel,name=ServerInfo
WebSphere:type=ThreadPoolStats,name=Default Executor
WebSphere:feature=restConnector,type=FileTransfer,name=FileTransfer


>>> mbeans_repo = collect( connection, True, "WebSphere:type=CollectiveRepository,*")

 MBean details for WebSphere:feature=collectiveController,type=CollectiveRepository,name=CollectiveRepository

   0 attributes

   13 operations

      create : Creates a new Node with the specified nodeName in the repository.
        nodeName [java.lang.String] :
          The fully qualified Node name, starting from the root "/".
        data [java.lang.Object] : The data to store in the Node, null is supported.

      delete : Deletes the specified Node and all nodes under it.
        nodeName [java.lang.String] :
          The fully qualified Node name, starting from the root "/".

      exists : Indicates whether or not the specified Node exists.
        nodeName [java.lang.String] :
          The fully qualified Node name, starting from the root "/".

      getData : Retrieves the data stored in the specified Node.
        nodeName [java.lang.String] :
          The fully qualified Node name, starting from the root "/".

      getDescendantData :
        Retrieves the data stored in the specified Node and the data of all of its
        descendants.
        nodeName [java.lang.String] :
          The fully qualified Node name, starting from the root "/".

      setData : Stores data in the specified Node.
        nodeName [java.lang.String] :
          The fully qualified Node name, starting from the root "/".
        data [java.lang.Object] :
          The data to store in the Node, null is supported.

      getChildren :
        Returns a collection of the names of the children Nodes of the specified Node.
        nodeName [java.lang.String] :
          The fully qualified Node name, starting from the root "/".
        absolutePath [boolean] :
          True if the returned collection should contain fully qualified node names.

      registerMember :
        Registers this member with the repository and starts the repository monitoring of
        this member.
        heartBeatInterval [int] :
          The heart beat interval, in seconds, for this member.
        memberData [java.util.Map] :  
          Provides data unique to this member; null may be provided if no data is required

      deregisterMember :
        Instructs the repository to unregister the specified member and discard any
        active repository services presently associated with the member.
        memberId [java.lang.String] :
          The member unregistering with the repository.

      sendHeartBeat :
        Sends a heart beat for the specified member to the repository.
        memberId [java.lang.String] :
          The member identifier to which the heart beat belongs.

      sendHeartBeat :
        Sends a heart beat for the specified member to the repository and allows the
        member to specify a new heart beat interval.
        memberId [java.lang.String] :
          The member identifier to which the heart beat belongs.
        newHeartBeatInterval [int] :
          The new heart beat interval, in seconds, for this member.

      dump :
        Writes the content of the specified Node to a file or the server log.
        nodeName [java.lang.String] :
          The fully qualified Node name, starting from the root "/".
        fileName [java.lang.String] :
          The file to dump the content to. Default to server log if null or empty.
        correlator [java.lang.String] :
          An optional string to identify the dump. It will be the first line of the dump
          if not null or empty.

      retrieveMemberRootCertificate : Unknown operation

By using the collectiveRepository MBean object, you can obtain the contents and members as shown in Listing 13.

Listing 13. Contents of the collectiveRepository MBean object
>>> mconnection = connection.getMBeanServerConnection()

>>> repo_content = mconnection.invoke( mbeans_repo[0], 'getDescendantData', [ '/'],
 [ 'java.lang.String'])

>>> for content in repo_content: print content
...
/
/sys.was.system
/sys.was.collectives
/sys.was.system/atlas
/sys.was.collectives/local
/sys.was.system/atlas/members
/sys.was.system/atlas/replicas
/sys.was.collectives/local/collective.uuid
/sys.was.collectives/local/hosts
/sys.was.collectives/local/adminCenter-1.0
/sys.was.collectives/local/collective.name
…

>>> mconnection.invoke( mbeans_repo[0], 'getChildren', ['/sys.was.collectives/local/hosts', False], ['java.lang.String', 'boolean'])
[<controller_hostname>, <server1_hostname>]

Define a utility function to list the collective members as shown in Listing 14. Notice the usage of the urllib2 module to decode the paths.

Listing 14. Defining a utility function to list the collective members
import urllib2

def getServersFromRepository( connection, repository_mbean):
  """
    param1: connection (return by connect() function)
    param2: mbean of the repository (return by collect( connection, [False|True], "WebSphere:type=CollectiveRepository,*")
    result: return the servers members defined in this repository
  """
  results = []
  mconn = connection.getMBeanServerConnection()
  # --- get hosts: [10.151.27.202, localhost]
  hosts = mconn.invoke(
                  repository_mbean,
                  'getChildren',
                  ['/sys.was.collectives/local/hosts', False],
                  ['java.lang.String', 'boolean'])
  # --- get userdirs for each host: [C%3A%2FIBM%2Fwlp_web%2Fusr]
  for host in hosts:
    print "\nhost: " + host
    userdirs = mconn.invoke(
                       repository_mbean,
                       'getChildren',
                       ['/sys.was.collectives/local/hosts/%s/userdirs' % host, False],
                       ['java.lang.String', 'boolean'])
    for userdir in userdirs:
      print "  userdir: " + str( urllib2.unquote( userdir))
      # --- get servers for this userdir: [controller, server1]
      servers = mconn.invoke(
                        repository_mbean,
                        'getChildren',
                        ['/sys.was.collectives/local/hosts/%s/userdirs/%s/servers'
                          % ( host, userdir), False],
                        ['java.lang.String', 'boolean'])
      for server in servers:
        print "   server: " + server
        results.append( {'host': host, 'userdir': userdir, 'server': server})
  return results

Display the collective repository content by using the utility function that you just defined in Listing 14. Listing 15 shows the collectiveRepository content.

Listing 15. The collectiveRepository content
>>> getServersFromRepository( connection, mbeans_repo[ 0])

host: <server1_hostname>
  userdir: $WLP_DIR/wlp/usr
   server: server1

host: <controller_hostname>
  userdir: $WLP_DIR/wlp/usr
   server: controller
[{'server': u'server1', 'host': u'<server1_hostname>',
 'userdir': u'$WLP_DIR%2Fwlp%2Fusr'},
 {'server': u'controller', 'host': u'<controller_hostname>',
  'userdir': u'$WLP_DIR%2Fwlp%2Fusr'}]

Now that you have the list of collective members, you can use the RoutingContext MBean object to redirect your request to each member.

Collect performance data for each collective member by using the RoutingContext MBean object

Now, you can connect to a Liberty server and then collect performance data for this server. If this server is a controller, you can list each of the collective members. To collect performance data from these members by using the controller, use the RoutingContext MBean of the controller.

Listing 16 shows how to get the attributes and methods of the RoutingContext MBean.

Listing 16. RoutingContext attributes and methods
>>> collect( connection, True, "WebSphere:type=RoutingContext,*")

 MBean details for WebSphere:feature=collectiveController,type=RoutingContext,name=RoutingContext

   0 attributes

   2 operations

      assignServerContext : Operation exposed for management
        hostName [java.lang.String] :
        userDir [java.lang.String] :
        serverName [java.lang.String] :

      assignHostContext : Operation exposed for management
        hostName [java.lang.String] :
array(java.lang.Object,
 [WebSphere:feature=collectiveController,type=RoutingContext,name=RoutingContext])

As shown in Listing 17, write the utility function that collects data from the collective controller.

Listing 17. Utility function to collect data from the collective controller
>>> def collect_controller( connector, details = False, objectName = Config[ 'objectName'], attributeName = Config[ 'attributeName']):
  """
    param1: connection object (return by connect() function)
    param2: output with or without details (True|False)
    param3: mbean object like "WebSphere:type=JvmStats,*"
    param4: attribute to retrieve in the mbean object
    result: return an array of mbeans objects found
    note  : try to loop through all the servers members found if there is a CollectiveRepository
  """
  mbeans = []
  mconnection = connector.getMBeanServerConnection()
  # --- look for a CollectiveRepository
  mbeans_repo = mconnection.queryNames(
                              ObjectName( Config[ 'collectiveName']), None).toArray()
  mbeans_rout = mconnection.queryNames(
                              ObjectName( Config[ 'routingName']), None).toArray()
  if len( mbeans_repo) > 0:
    for mbean_repo in mbeans_repo:
      # --- for each repo, collect data for each members
      servers = getServersFromRepository( connector, mbean_repo)
      for mbean_rout in mbeans_rout:
        for server in servers:
          routing_context = mconnection.invoke(
             mbean_rout,
            'assignServerContext',
            [ server[ 'host'],
              str( urllib2.unquote( server[ 'userdir'])),
              server[ 'server']],
            ['java.lang.String', 'java.lang.String', 'java.lang.String'])
          print("\n# --- collecting for %s:%s:%s" %
                 ( server[ 'host'], server[ 'userdir'], server[ 'server']))
          print "        routing_context: " + str( routing_context)
          results = collect( connector, details, objectName, attributeName)
          mbeans.append( results)
    return mbeans
  else:
    print "No CollectiveRepository found..."

You have now defined all utility functions. Listing 18 shows how to gather data from the collective controller members data by using the utility functions.

Listing 18. Collecting data from the collective controller members
>>> servers_info = collect_controller( connection, True, "WebSphere:name=ServerInfo,*")

host: <server1_hostname>
  userdir: $WLP_DIR/wlp/usr
   server: server1

host: <controller_hostname>
  userdir: $WLP_DIR/wlp/usr
   server: controller

# --- collecting for <server1_hostname>:$WLP_DIR%2Fwlp%2Fusr:server1
        routing_context: True

 MBean details for WebSphere:feature=kernel,name=ServerInfo

   4 attributes
      DefaultHostname [java.lang.String] = <server1_hostname>
      UserDirectory [java.lang.String] = $WLP_DIR/wlp/usr/
      InstallDirectory [java.lang.String] = $WLP_DIR/wlp/
      Name [java.lang.String] = server1

   0 operations

# --- collecting for <controller_hostname>:$WLP_DIR%2Fwlp%2Fusr:controller
        routing_context: True

 MBean details for WebSphere:feature=kernel,name=ServerInfo

   4 attributes
      DefaultHostname [java.lang.String] = <controller_hostname>
      UserDirectory [java.lang.String] = $WLP_DIR/wlp/usr/
      InstallDirectory [java.lang.String] = $WLP_DIR/wlp/
      Name [java.lang.String] = controller

   0 operations

Use the last utility function to get the PMI data from the collective controller as shown in Listing 19.

Listing 19. Collecting PMI data from the collective controller
>>> servers_jvmstats = collect_controller( connection, True, "WebSphere:type=JvmStats,*")
No CollectiveRepository found...

>>> connection.disconnect()
>>> connection = connect()
9443
../usr/servers/controller/resources/security/key.jks
Connecting to the server...
Successfully connected to the server "<controller_hostname>:9443"

>>> servers_jvmstats = collect_controller( connection, True, "WebSphere:type=JvmStats,*")

host: <server1_hostname>
  userdir: $WLP_DIR/wlp/usr
   server: server1

host: <controller_hostname>
  userdir: $WLP_DIR/wlp/usr
   server: controller

# --- collecting for <server1_hostname>:$WLP_DIR%2Fwlp%2Fusr:server1
        routing_context: True

 MBean details for WebSphere:type=JvmStats

   7 attributes
      UsedMemory [long] = 33044912
      FreeMemory [long] = 13342288
      Heap [long] = 46792704
      UpTime [long] = 69644602
      ProcessCPU [double] = 0.118396306716
      GcCount [long] = 309
      GcTime [long] = 649

   0 operations

# --- collecting for <controller_hostname>:$WLP_DIR%2Fwlp%2Fusr:controller
        routing_context: True

 MBean details for WebSphere:type=JvmStats

   7 attributes
      UsedMemory [long] = 57614496
      FreeMemory [long] = 13676384
      Heap [long] = 72417280
      UpTime [long] = 69657171
      ProcessCPU [double] = 0.0867987941057
      GcCount [long] = 432
      GcTime [long] = 1025

   0 operations

Conclusion

In this tutorial, you learned how to use Jython scripts to collect performance data from a server or from a collective controller and all its members. By following these steps, you can see the power of introspection to find the MBeans that you need and how to start them.

Acknowledgements

Special thanks goes to Michael C. Thompson for reviewing this tutorial series and providing his input.

Resources

The following resources are helpful when reading this tutorial:


Downloadable resources


Comments

Sign in or register to add and subscribe to comments.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Cloud computing, Middleware
ArticleID=1027244
ArticleTitle=Retrieve performance metrics from the WebSphere Liberty profile, Part 2: Data collection by using Jython
publish-date=02192016