package com.ibm.dtfj.analyzer.was.samples;import java.util.Iterator;import com.ibm.dtfj.analyzer.ext.IAnalysisReport;
import com.ibm.dtfj.analyzer.ext.IMessageLogger;
import com.ibm.dtfj.analyzer.ext.IReport;
import com.ibm.dtfj.analyzer.helpers.objectwrapper.ObjectWrapper;
import com.ibm.dtfj.analyzer.helpers.objectwrapper.ObjectWrapperCollection;
import com.ibm.dtfj.analyzer.j2se.wrappers.HashMapWrapper;
import com.ibm.dtfj.analyzer.was.WASHeader;
import com.ibm.dtfj.analyzer.was.WASVersion;
import com.ibm.dtfj.analyzer.was.base.WASAnalyzerBase;
import com.ibm.dtfj.java.JavaRuntime;/**
* Sample analyzer to print the WAS threads pools - version X
*/
public class WASThreadPoolsSampleX extends WASAnalyzerBase implements IReport { /**
* @see com.ibm.dtfj.analyzer.ext.IAnalyzerBase#getVersion()
*/
public String getVersion() {
return "1.0.0.20080310-EXPERIMENTAL(alpha)";
} /**
* @see com.ibm.dtfj.analyzer.ext.IAnalyzerBase#getName()
*/
public String getName() {
return "WASThreadPoolsSampleX";
} /**
* @see com.ibm.dtfj.analyzer.ext.IAnalyzerBase#getShortDescription()
*/
public String getShortDescription() {
return getString("A sample analyzer that demonstrates how to write analysis modules (using WAS thread pools as an example)");
} /**
* @see com.ibm.dtfj.analyzer.ext.IAnalyzerBase#getLongDescription()
*/
public String getLongDescription() {
return (
getShortDescription() + "\n" +
getVersion() + "\n" +
"This is the complete version of the sample analyzer from the tutorial "Writing Dump Analyzer modules for WAS diagnostics"" +
"that is provided with the Dump Analyzer tool documentation");
} /**
* @see com.ibm.dtfj.analyzer.ext.IAnalyzerBase#isPrimaryAnalyzer()
*/
public boolean isPrimaryAnalyzer() {
return true;
} /**
* @see com.ibm.dtfj.analyzer.ext.IAnalyzerBase#getCategories()
*/
public String[] getCategories() {
return new String[] {
getClass().getPackage().getName()
};
} /*
* Some state being built as part of the analysis
*/
private int numberOfPools = 0;
private int numberOfAllocatedThreads = 0;
private int numberOfPossibleThreads = 0;
private int numberOfErrors = 0; /*
* A threshold to warn of possible thread overload (% of allocated vs. possible threads)
* (not necessarily appropriate for actual problem detection; just to show the principle of such observations)
*/
private final static int THREAD_OVERLOAD_THRESHOLD = 80; /**
* @see com.ibm.dtfj.analyzer.ext.IReport#produceReport()
*/
public IAnalysisReport produceReport() {
IAnalysisReport mainReport = allocateReport(null);
IAnalysisReport summaryStatsReport = allocateSecondaryReport("summaryStats", null);
IAnalysisReport summaryListReport = allocateSecondaryReport("summaryList", null);
IAnalysisReport detailsReport = allocateSecondaryReport("details", null); /*
* Print a global header for this report
*/
WASHeader wasHeader = (WASHeader) getContext().loadAnalyzer(WASHeader.class.getName());
IAnalysisReport headerReport = wasHeader.produceReport();
mainReport.printReport("Common WAS header information", headerReport, IAnalysisReport.TAG_MAJORHEADING); /*
* Check that the WAS version is compatible with this analyzer (but continue anyway even if not)
*/
WASVersion wasVersion = (WASVersion) getContext().loadAnalyzer(WASVersion.class.getName());
wasVersion.checkCompatibleVersion(mainReport, "WASThreadPoolsBasic", new String[] { "6.1" }, false); //$NON-NLS-1$ //$NON-NLS-2$ /*
* Scan all the pools to collect both summary and detailed information
*/
scanAllPools(summaryStatsReport, summaryListReport, detailsReport); /*
* Print the summary information
*/
mainReport.startSection("Summary information", IAnalysisReport.TAG_MAJORHEADING);
mainReport.printReport("Global Statistics", summaryStatsReport);
mainReport.printReport("Summary list of pools", summaryListReport);
mainReport.endSection(); /*
* Print the detailed information
*/
mainReport.printReport("Detailed information", detailsReport, IAnalysisReport.TAG_MAJORHEADING); return mainReport;
} private void scanAllPools(IAnalysisReport summaryStatsReport, IAnalysisReport summaryListReport, IAnalysisReport detailsReport) {
/*
* Iterate over all the pools, computing the global statistics and bulding a list
*/
ObjectWrapperCollection pools = ObjectWrapperCollection.getObjectInstances(getContext(), "com/ibm/ws/util/ThreadPool");
for (int index = 0; index < pools.size(); index++) {
ObjectWrapper pool = (ObjectWrapper) pools.get(index);
scanOnePool(pool, summaryListReport, detailsReport);
} /*
* Generate the global statistics report
*/
summaryStatsReport.printField("Number of pools successfully scanned", numberOfPools);
summaryStatsReport.printField("Number of pools scanned with errors", numberOfErrors);
summaryStatsReport.printField("Current number of pool threads", numberOfAllocatedThreads);
summaryStatsReport.printField("Maximum possible number of pool threads", numberOfPossibleThreads);
summaryStatsReport.printField("Number of JVM threads not in a pool", countJVMThreads() - numberOfAllocatedThreads);
if (numberOfAllocatedThreads > ((THREAD_OVERLOAD_THRESHOLD / 100.0f) * numberOfPossibleThreads)) {
logMessage(IMessageLogger.LEVEL_DBDA_OBSERVATION_LOW,
"(minor observation) This process is currently using more than {0}% of all possible threads ({1}/{2})",
new Object[] { new Integer(THREAD_OVERLOAD_THRESHOLD),
new Integer(numberOfAllocatedThreads),
new Integer(numberOfPossibleThreads) },
summaryStatsReport);
}
} private void scanOnePool(ObjectWrapper pool, IAnalysisReport summaryListReport, IAnalysisReport detailsReport) {
int curSize;
int maxSize; try {
/*
* Generate one line of output for this pool in the summary report
*/
summaryListReport.startFormatSection(IAnalysisReport.FORMAT_COLUMNS, "2 1 1"); {
pool.printValueAtPath(summaryListReport, "", "name");
pool.printValueAtPath(summaryListReport, "Size", "poolSize_");
pool.printValueAtPath(summaryListReport,"", "");
} summaryListReport.endSection(); /*
* Generate a detailed record for this pool in the details report
*/
IAnalysisReport out2 = pool.startPrintGroup(detailsReport, "Thread Pool", pool.getParent(), ObjectWrapper.MODE_NONE, IAnalysisReport.TAG_STANDOUT); {
pool.printValueAtPath(out2, "Pool name", "name");
out2.startFormatSection(IAnalysisReport.FORMAT_COLUMNS, "1 1"); {
pool.printValueAtPath(out2, "Min size", "minimumPoolSize_");
maxSize = pool.printValueAtPath(out2, "Max size", "maximumPoolSize_").getIntegerValue();
} out2.endSection();
curSize = pool.printValueAtPath(out2, "Current size", "poolSize_").getIntegerValue();
pool.printCollectionValueReportsAtPath(out2, "List of Threads", "Thread", "threads_", HashMapWrapper.class.getName(), ThreadPoolWorkerWrapper.class.getName());
} pool.endPrintGroup(); /*
* Update global statistics
*/
numberOfAllocatedThreads += curSize;
numberOfPossibleThreads += maxSize;
numberOfPools++;
} catch (Exception e) {
logExceptionMessage("Error extracting information for pool", e, summaryListReport);
numberOfErrors++;
}
} /**
* Use low-level DTFJ primitives to count the total number of threads in this JVM
* (independent of whether they are in a WAS thread pool or not)
* @return the number of JVM threads, according to DTFJ
*/
private int countJVMThreads() {
JavaRuntime runtime = getContext().getCurrentJavaRuntime();
Iterator it = runtime.getThreads();
int count = 0;
while (it.hasNext()) {
it.next();
count++;
}
return count;
}
}
package com.ibm.dtfj.analyzer.was.samples;
import com.ibm.dtfj.analyzer.ext.IAnalysisReport;
import com.ibm.dtfj.analyzer.ext.IReport;
import com.ibm.dtfj.analyzer.ext.IWrapper;
import com.ibm.dtfj.analyzer.helpers.objectwrapper.ObjectWrapper;
import com.ibm.dtfj.analyzer.util.IdentityStringHelper;/**
* Sample wrapper for a com/ibm/ws/util/ThreadPool$Worker
*/
public class ThreadPoolWorkerWrapper extends ObjectWrapper implements IReport, IWrapper {
/**
* @see com.ibm.dtfj.analyzer.ext.IWrapper#setParent(Object)
*/
public void setParent(Object parent) {
super.setParent(parent);
if (! this.isInstanceOf("com/ibm/ws/util/ThreadPool$Worker")) {
throw new IllegalArgumentException("Attempting to initialize a ThreadPoolWorkerWrapper with an object of the wrong type " + IdentityStringHelper.buildIdentString(parent));
}
}
/**
* @see com.ibm.dtfj.analyzer.ext.IReport#produceReport()
*/
public IAnalysisReport produceReport() {
IAnalysisReport out = allocateReport(null);
this.printValueAtPath(out, "Thread name", "name");
this.printValueAtPath(out, "Thread number", "threadNumber");
this.printValueAtPath(out, "Priority", "priority");
this.printValueAtPath(out, "Start time", "startTime");
return out;
}
}