WebSphere Performance Monitoring jython script
Contents |
[edit] About
This script allows you to collect WebSphere Performance Statistics continuously into a CSV file to analyze later with Excel or similar tools. The script is written in jython and runs under the wsadmin shell shipped with all WebSphere distributions.
The script sits in the background and pulls statistics from a select number of MBeans provided by WAS. It can be modified to pull specific MBeans and their statistics on demand. If you want to see what statistics is available run the script with the -l option.
The script can run as a service under Windows, which provides an independent facility to start and stop performance monitoring. In order to function as a Windows service the script uses Windows Management Instrumentation (WMI) to monitor parent process and shutdown itself when the parent is terminated. If you are running on a non-Windows platform you need to comment out a system call for the WMI. See below for more details.
[edit] Setting it up
The following instructions assume a default WebSphere install on Windows on the F: drive. Change the paths according to your specific environment. For a non-Windows environment use the following directions as a reference and adjust for bash/dash/ksh accordingly.
- First make sure the WebSphere Performance Monitoring Infrastructure is enabled.
- Make sure your jython shell is setup properly by running
"f:\Program Files\IBM\WebSphere\AppServer\bin\wsadmin.bat" -lang jython -user %ADMIN% -password %ADMINPWD%
- Run the script with the -l option to figure out what statistics you need. By default the scripts pulls all stats from the JVM, MQThread and System MBeans. You can skip this step is JVM, MQ and System is all you need.
"f:\Program Files\IBM\WebSphere\AppServer\bin\wsadmin.bat" -lang jython -user %ADMIN% -password %ADMINPWD% -f f:\apiscript\bin\collectWASPerformanceStats.py -l > allstats.txt
- Modify the script for the specific stats you are interested in.
- Run the script with a provided batch file, or use the following command line:
"f:\Program Files\IBM\WebSphere\AppServer\bin\wsadmin.bat" -lang jython -user %ADMIN% -password %ADMINPWD% -f f:\apiscript\bin\collectWASPerformanceStats.py stats.csv
- If running on a non-Windows environment find the following line in the script
# COMMENT OUT or delete the code from here to the end of file if not running on Windows
and do exactly that
[edit] How to install the script as a Windows service
Adjust the paths according to your environment in the following directions
- Get and install the Windows resource kit
- Run the following
instsrv.exe "WebSphere Performance Monitor" "C:\Program Files\Windows Resource Kits\Tools\srvany.exe"
- Create the Parameters key in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WebSphere Performance Monitor
- Add the Application string value under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WebSphere Performance Monitor\Parameters that reads
cmd /c F:\apiscript\bin\collectWASPerformanceStats.bat
[edit] WebSphere Performance Collection governor
The following batch file is provided for convenience. It allows the jython script to run by either running
collectWASPerformanceStats.bat
from the command line or by installing it as a Windows service. To run the script with the batch file, create a collectWASPerformanceStats.properties file in the same directory as the jython script and specify the following values:
enrole.appServer.ejbuser.credentials = WAS admin name (wsadmin) enrole.appServer.ejbuser.principal = WAS admin password
By default the statistics is saved into f:\temp\stats.csv. The logs go to f:\temp\stats.log. You can change the location of these files by editing the governor batch.
@echo off rem A round-about Microsoft way to get a parameter value for /f "delims==; tokens=2" %%G in ('findstr enrole.appServer.ejbuser.principal collectWASPerformanceStats.properties') do set ADMIN=%%G for /f "delims==; tokens=2" %%G in ('findstr enrole.appServer.ejbuser.credentials collectWASPerformanceStats.properties') do set ADMINPWD=%%G echo Starting the statistics collection to f:/temp/stats.csv. Output sent to f:/temp/stats.log. Press ctrl-c to stop ... echo ------------------------------------------------------- >> f:/temp/stats.log echo %date% %time%. Starting... >> f:/temp/stats.log call "f:\Program Files\IBM\WebSphere\AppServer\bin\wsadmin.bat" -lang jython -user %ADMIN% -password %ADMINPWD% -f f:\apiscript\bin\collectWASPerformanceStats.py f:/temp/stats.csv >> f:/temp/stats.log echo %date% %time%. Stopped. >> f:/temp/stats.log
[edit] WebSphere Performance Collection script
The script itself: Download
''' Queries current running WAS stats and saves them to a file (C) 2011 Alex Ivkin Run using the following command: "f:\Program Files\IBM\WebSphere\AppServer\bin\wsadmin.bat" -lang jython -user wsadmin -password wsadmin -f collectWASPerformanceStats.py <stats_file> [-l] NOTE: Due to WebSphere weirdness you have to use FORWARD slashes in the file name. Otherwise the backward slashes need to be doubled or they will turn into escape sequences Use -l to export the list of all available performance MBeans to the output file and quit ''' import re,sys,time,os,java if len(sys.argv)==0: print __doc__ sys.exit(1) perfObject = AdminControl.completeObjectName('type=Perf,*') #@UndefinedVariable - comes from WAS if perfObject is None or perfObject == "": print "Can not retreive the performance MBean. Make sure PMI (performance metrics) is enabled on the server" perfOName = AdminControl.makeObjectName(perfObject) #@UndefinedVariable writeHeader=1 try: if os.path.isfile(sys.argv[0]): writeHeader=0 # do not write a header to a file that is being appeneded f_out=open(sys.argv[0],"a") except: print "Error opening file %s\n%s" % (sys.argv[0],sys.exc_info()[1]) sys.exit(2) if len(sys.argv) > 1: if sys.argv[1]=='-l': # list objects with stats print "Listing objects ..." for a in AdminControl.queryNames('*').split('\n'): #type=ConnectionPool, @UndefinedVariable try: config=AdminControl.invoke_jmx(perfOName, 'getConfig', [AdminControl.makeObjectName(a)], ['javax.management.ObjectName']) if config is not None: print >> f_out, a except: pass print "done." sys.exit(0) # Enable PMI data using the pre-defined statistic sets. AdminControl.invoke_jmx (perfOName, 'setStatisticSet', ['all'], ['java.lang.String']) #@UnusedVariable @UndefinedVariable WASobjects={} # specify which stat objects to pull WASobjects['JVM']=AdminControl.makeObjectName(AdminControl.completeObjectName('type=JVM,*')) #@UndefinedVariable WASobjects['MQThread'] = AdminControl.makeObjectName(AdminControl.completeObjectName('name=SIBJMS*,type=ThreadPool,*')) #SIBJMS* or WebContainer @UndefinedVariable WASobjects['System'] = AdminControl.makeObjectName(AdminControl.completeObjectName('name=SystemMetrics,*')) #@UndefinedVariable namelist=['Date','Time'] # used for ordering, hashtables are unordered # list all possible stats for obj in WASobjects.keys(): statconfig=AdminControl.invoke_jmx(perfOName, 'getConfig', [WASobjects[obj]], ['javax.management.ObjectName']) for d in statconfig.listAllData(): namelist.append(obj+d.name) # Simulate CSV. csv library is not available in WAS's outdated jython if writeHeader: print>>f_out,",".join(namelist) def run(cmd): ''' Use Java exec command to run a script due to Jython 2.1 limitations''' process = java.lang.Runtime.getRuntime().exec(cmd) stdoutstream = '' errorstream = '' running = 1 while running: while process.getInputStream().available(): # > 0: stdoutstream += chr(process.getInputStream().read()) while process.getErrorStream().available(): # > 0: errorstream += chr(process.getErrorStream().read()) try: process.exitValue() # OK, we're done simulating: running = 0 #print "done..." return (stdoutstream,errorstream) except java.lang.IllegalThreadStateException, e: # In case of this exception the process is still running. #print "running..." # pass time.sleep(0.1) def get_value(s): value=1 if str(s.getClass())=='com.ibm.ws.pmi.stat.BoundedRangeStatisticImpl': # bounded range value=s.current elif str(s.getClass())=='com.ibm.ws.pmi.stat.CountStatisticImpl': # count statistics value=s.count elif str(s.getClass())=='com.ibm.ws.pmi.stat.DoubleStatisticImpl': value=s.double elif str(s.getClass())=='com.ibm.ws.pmi.stat.TimeStatisticImpl': # max, min, minTime,maxTime, totalTime, sumOfSquares, delta, mean value=s.count elif str(s.getClass())=='com.ibm.ws.pmi.stat.RangeStatisticImpl': # lowWaterMark, highWaterMark, integral, delta, mean, current value=s.current elif str(s.getClass())=='com.ibm.ws.pmi.stat.AverageStatisticImpl': # max, mean,min,sumOfSquares,total value=s.count else: print s.getClass() return value print "Pulling Websphere statistics...Press Ctrl-C to interrupt" while 1: try: statshash={} for t in namelist: if t=="Date": statshash[t]=time.strftime("%m/%d/%Y", time.localtime()) elif t=="Time": statshash[t]=time.strftime("%H:%M:%S", time.localtime()) else: statshash[t]="" for obj in WASobjects.keys(): stats=AdminControl.invoke_jmx(perfOName, 'getStatsObject', [WASobjects[obj], java.lang.Boolean ('false')], ['javax.management.ObjectName', 'java.lang.Boolean']) # threadstats=AdminControl.invoke_jmx(perfOName, 'getStatsObject', [threadOName, java.lang.Boolean ('false')], ['javax.management.ObjectName', 'java.lang.Boolean']) # print jvmstats.class # com.ibm.websphere.pmi.stat.StatsImpl at http://publib.boulder.ibm.com/infocenter/dmndhelp/v6rxmx/index.jsp?topic=/com.ibm.wsps.602.javadoc.doc/doc/com/ibm/websphere/pmi/stat/StatsImpl.html #statshash=dict(zip(typehash.keys()),[0]*len(typehash.keys())) for s in stats.statistics: statshash[obj+s.name]=get_value(s) #print statshash print>>f_out,",".join([str(statshash[v]) for v in namelist]) except: # att Printing the traceback may cause memory leaks in Python 2.1 due to circular references. see here http://docs.python.org/library/sys.html print "%s. Encountered a glitch: %s, %s" % (time.strftime("%m/%d/%Y %H:%M:%S", time.localtime()),sys.exc_info()[0],sys.exc_info()[1]) time.sleep(60) # collection delay # COMMENT OUT or delete the code from here to the end of file if not running on Windows # check if the parent process is up # there is a small bug - sys.argv[0] is the FIRST argument (i.e the real arg, not the script name) under wsadmin, but this is ok here. # another small bug - due to the slow cycle time (see time.sleep(60)) it may take up to a minute for the java process to go down #ret1=run("wmic process where (commandline like '%"+sys.argv[0]+"%' and name like 'java.exe') get parentprocessid") #parentprocessid=re.search(r'\d{2,}',ret1[0]).group(0) #ret2=run("wmic process where (processid='"+parentprocessid+"') get name") #if re.match('No Instance.*',ret2[1]): # print "The parent process is dead. Going down." # sys.exit(10)