IT WORKS! FINALLY! HURRAY! Thanks so much for your patience and help
-----------------SOURCE CODE------------------------------
package kg.apc.jmeter.tomcatmon;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import org.apache.jmeter.reporters.ResultCollector;
import org.apache.jmeter.samplers.SampleEvent;
import org.apache.jmeter.testelement.property.CollectionProperty;
import org.apache.jmeter.testelement.property.JMeterProperty;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
/**
*
* @author MrBrik
* based on code of PerfMonCollector, author APC
*/
public class TomcatMonCollector
extends ResultCollector
implements Runnable {
public int threadsCount = 0;
public int httpThreadsCount = 0;
public String type = "";
ThreadMXBean threadmxbean;
JMXConnector connector;
private static final String PERFMON = "TomcatMon";
private static final Logger log =
LoggingManager.getLoggerForClass();
public static final String DATA_PROPERTY = "metricConnections";
private Thread workerThread;
private HashMap<String, Long> oldValues = new HashMap<String,
Long>();
public void setData(CollectionProperty rows) {
setProperty(rows);
}
public JMeterProperty getData() {
return getProperty(DATA_PROPERTY);
}
@Override
public void sampleOccurred(SampleEvent event) {
// just dropping regular test samples
}
public synchronized void run() {
while (true) {
processConnectors();
try {
this.wait(1000);
}
catch (InterruptedException ex) {
log.debug("Monitoring thread was interrupted", ex);
break;
}
}
}
@Override
public void testStarted(String host) {
try {
initiateConnectors();
} catch (MalformedURLException ex) {
java.util.logging.Logger.getLogger(TomcatMonCollector.class.getName()).log(Level.SEVERE,
null, ex);
}
workerThread = new Thread(this);
workerThread.start();
super.testStarted(host);
}
@Override
public void testEnded(String host) {
workerThread.interrupt();
shutdownConnectors();
super.testEnded(host);
}
private void initiateConnectors() throws MalformedURLException {
oldValues.clear();
JMeterProperty prop = getData();
if (!(prop instanceof CollectionProperty)) {
log.warn("Got unexpected property: " + prop);
return;
}
CollectionProperty rows = (CollectionProperty) prop;
ArrayList<Object> row = (ArrayList<Object>)
rows.get(0).getObjectValue();
String host = ((JMeterProperty)
row.get(0)).getStringValue();
int port = ((JMeterProperty) row.get(1)).getIntValue();
type = ((JMeterProperty) row.get(2)).getStringValue();
try {
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///
jndi/rmi://"+host+":" + port + "/jmxrmi");
connector = JMXConnectorFactory.connect(url);
MBeanServerConnection mbsc =
connector.getMBeanServerConnection();
threadmxbean =
ManagementFactory.newPlatformMXBeanProxy(mbsc,
ManagementFactory.THREAD_MXBEAN_NAME, ThreadMXBean.class);
threadmxbean.setThreadContentionMonitoringEnabled(true);
} catch (IOException ex) {
java.util.logging.Logger.getLogger(TomcatMonCollector.class.getName()).log(Level.SEVERE,
null, ex);
}
}
private void shutdownConnectors() {
try {
connector.close();
} catch (IOException ex) {
java.util.logging.Logger.getLogger(TomcatMonCollector.class.getName()).log(Level.SEVERE,
null, ex);
}
}
private void processConnectors() {
httpThreadsCount = 0;
threadsCount = threadmxbean.getThreadCount();
long[] ids = threadmxbean.getAllThreadIds();
ThreadInfo[] list = threadmxbean.getThreadInfo(ids);
if(type.contains("http") || type.contains("HTTP"))
{
String str = Arrays.deepToString(list);
Pattern p = Pattern.compile("http");
Matcher m = p.matcher(str);
while (m.find()){
httpThreadsCount +=1;
}
generateSample(httpThreadsCount, "HTTP Threads");
}
else generateSample(threadsCount, "Live Threads");
}
private void generateSample(long value, String label) {
TomcatMonSampleResult res = new TomcatMonSampleResult();
res.setSampleLabel(label);
res.setValue(value);
SampleEvent e = new SampleEvent(res, PERFMON);
super.sampleOccurred(e);
}
}
----
I added TomcatMonSampleResult to my package just to be sure that i'm
not taking smtn from perfmon package. It's code is just the same as
PerfMonSampleResult.
package kg.apc.jmeter.vizualizers;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import javax.swing.BorderFactory;
import javax.swing.DefaultCellEditor;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import kg.apc.jmeter.JMeterPluginsUtils;
import kg.apc.jmeter.charting.AbstractGraphRow;
import kg.apc.jmeter.gui.ButtonPanelAddCopyRemove;
import kg.apc.jmeter.tomcatmon.TomcatMonCollector;
import org.apache.jmeter.gui.util.PowerTableModel;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.property.CollectionProperty;
import org.apache.jmeter.testelement.property.JMeterProperty;
import org.apache.jmeter.testelement.property.NullProperty;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
/**
*
* @author MrBrik
* based on code of PerfMonGui, author APC
*/
public class TomcatMonGui
extends AbstractOverTimeVisualizer {
private static final Logger log =
LoggingManager.getLoggerForClass();
private PowerTableModel tableModel;
private JTable grid;
private JTextField metricTypesBox;
public static final String[] columnIdentifiers = new String[]{
"Host / IP", "Port", "Metric type(http or all)", ""
};
public static final Class[] columnClasses = new Class[]{
String.class, String.class, String.class, String.class
};
private static String[] defaultValues = new String[]{
"localhost", "4444", "HTTP threads", ""
};
public TomcatMonGui() {
super();
graphPanel.getGraphObject().setyAxisLabel("Number of threads");
graphPanel.getGraphObject().setExpendRows(true);
initGui();
}
@Override
protected JSettingsPanel createSettingsPanel() {
return new JSettingsPanel(this,
JSettingsPanel.GRADIENT_OPTION
| JSettingsPanel.LIMIT_POINT_OPTION
| JSettingsPanel.MAXY_OPTION
| JSettingsPanel.RELATIVE_TIME_OPTION);
}
@Override
public String getWikiPage() {
return "PerfMon";
}
public String getLabelResource() {
return getClass().getSimpleName();
}
@Override
public String getStaticLabel() {
return JMeterPluginsUtils.prefixLabel("Tomcat Threads
Collector");
}
private void initGui() {
add(createConnectionsPanel(), BorderLayout.SOUTH);
}
private Component createConnectionsPanel() {
JPanel panel = new JPanel(new BorderLayout(5, 5));
panel.setBorder(BorderFactory.createTitledBorder("Server
info"));
panel.setPreferredSize(new Dimension(150, 150));
JScrollPane scroll = new JScrollPane(createGrid());
scroll.setPreferredSize(scroll.getMinimumSize());
panel.add(scroll, BorderLayout.CENTER);
panel.add(new ButtonPanelAddCopyRemove(grid, tableModel,
defaultValues), BorderLayout.SOUTH);
metricTypesBox=new JTextField();
grid.getColumnModel().getColumn(2).setCellEditor(new
DefaultCellEditor(metricTypesBox));
return panel;
}
private JTable createGrid() {
grid = new JTable();
createTableModel();
grid.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
grid.setMinimumSize(new Dimension(200, 100));
return grid;
}
private void createTableModel() {
tableModel = new PowerTableModel(columnIdentifiers,
columnClasses);
grid.setModel(tableModel);
}
@Override
public TestElement createTestElement() {
TestElement te = new TomcatMonCollector();
modifyTestElement(te);
te.setComment(JMeterPluginsUtils.getWikiLinkText(getWikiPage()));
return te;
}
@Override
public void modifyTestElement(TestElement te) {
super.modifyTestElement(te);
if (grid.isEditing()) {
grid.getCellEditor().stopCellEditing();
}
if (te instanceof TomcatMonCollector) {
TomcatMonCollector pmte = (TomcatMonCollector) te;
CollectionProperty rows =
JMeterPluginsUtils.tableModelRowsToCollectionProperty(tableModel,
TomcatMonCollector.DATA_PROPERTY);
pmte.setData(rows);
}
super.configureTestElement(te);
}
@Override
public void configure(TestElement te) {
super.configure(te);
TomcatMonCollector pmte = (TomcatMonCollector) te;
JMeterProperty perfmonValues = pmte.getData();
if (!(perfmonValues instanceof NullProperty)) {
JMeterPluginsUtils.collectionPropertyToTableModelRows((CollectionProperty)
perfmonValues, tableModel);
}
else {
log.warn("Received null property instead of collection");
}
}
@Override
public void add(SampleResult res) {
super.add(res);
addThreadGroupRecord(res.getSampleLabel(),
normalizeTime(res.getEndTime()), res.getLatency());
updateGui(null);
}
private void addThreadGroupRecord(String threadGroupName, long
time, long value) {
AbstractGraphRow row = model.get(threadGroupName);
if (row == null) {
row = getNewRow(model, AbstractGraphRow.ROW_AVERAGES,
threadGroupName,
AbstractGraphRow.MARKER_SIZE_NONE, false, false, false,
true, true);
}
row.add(time, value);
}
}
Changed type of metricsTypeBox to JTextField for my needs. My plugin
can show 2 types of metrics - HTTP Threads and just ALL threads,
depending on what is typed in the 3rd column
You can add this to your package, i think it would be great :)