mirror of https://github.com/apache/activemq.git
- Added a configurable report generator that could generate output either verbose or to an xml file.
- Using sysTest.reportType=[verbose|xml], default is xml. - Xml output also displays a summary verbosely. - TODO: Update the mojo to accomodate the additional option. git-svn-id: https://svn.apache.org/repos/asf/incubator/activemq/trunk@413651 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
fcc9ae70b1
commit
77c889d19e
|
@ -18,6 +18,9 @@ package org.apache.activemq.tool;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.apache.activemq.tool.reports.VerbosePerfReportWriter;
|
||||||
|
import org.apache.activemq.tool.reports.PerformanceReportWriter;
|
||||||
|
import org.apache.activemq.tool.reports.XmlFilePerfReportWriter;
|
||||||
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -29,17 +32,20 @@ public abstract class JmsClientSystemSupport {
|
||||||
public static final String DEST_DISTRO_ALL = "all"; // Each client will send/receive to all destination;
|
public static final String DEST_DISTRO_ALL = "all"; // Each client will send/receive to all destination;
|
||||||
public static final String DEST_DISTRO_EQUAL = "equal"; // Equally divide the number of destinations to the number of clients
|
public static final String DEST_DISTRO_EQUAL = "equal"; // Equally divide the number of destinations to the number of clients
|
||||||
public static final String DEST_DISTRO_DIVIDE = "divide"; // Divide the destination among the clients, even if some have more destination than others
|
public static final String DEST_DISTRO_DIVIDE = "divide"; // Divide the destination among the clients, even if some have more destination than others
|
||||||
|
public static final String REPORT_VERBOSE = "verbose";
|
||||||
protected static final String KEY_CLIENT_DEST_COUNT = "client.destCount";
|
public static final String REPORT_XML_FILE = "xml";
|
||||||
protected static final String KEY_CLIENT_DEST_INDEX = "client.destIndex";
|
|
||||||
|
|
||||||
protected Properties sysTestSettings = new Properties();
|
protected Properties sysTestSettings = new Properties();
|
||||||
protected Properties samplerSettings = new Properties();
|
protected Properties samplerSettings = new Properties();
|
||||||
protected Properties jmsClientSettings = new Properties();
|
protected Properties jmsClientSettings = new Properties();
|
||||||
protected ThreadGroup clientThreadGroup;
|
protected ThreadGroup clientThreadGroup;
|
||||||
protected PerfMeasurementTool performanceSampler;
|
protected PerfMeasurementTool performanceSampler;
|
||||||
protected String reportDirectory = "";
|
|
||||||
|
|
||||||
|
protected String reportType = REPORT_XML_FILE;
|
||||||
|
protected String reportDirectory = "./";
|
||||||
|
protected String reportName = null;
|
||||||
|
|
||||||
|
protected String clientName = null;
|
||||||
protected int numClients = 1;
|
protected int numClients = 1;
|
||||||
protected int totalDests = 1;
|
protected int totalDests = 1;
|
||||||
protected String destDistro = DEST_DISTRO_ALL;
|
protected String destDistro = DEST_DISTRO_ALL;
|
||||||
|
@ -49,12 +55,11 @@ public abstract class JmsClientSystemSupport {
|
||||||
performanceSampler = new PerfMeasurementTool();
|
performanceSampler = new PerfMeasurementTool();
|
||||||
performanceSampler.setSamplerSettings(samplerSettings);
|
performanceSampler.setSamplerSettings(samplerSettings);
|
||||||
|
|
||||||
PerfReportGenerator report = new PerfReportGenerator();
|
PerformanceReportWriter writer = createPerfWriter();
|
||||||
report.setReportName(this.getClass().getName());
|
performanceSampler.setPerfWriter(writer);
|
||||||
report.setTestSettings(getSettings());
|
|
||||||
report.startGenerateReport();
|
|
||||||
|
|
||||||
performanceSampler.setWriter(report.getWriter());
|
writer.openReportWriter();
|
||||||
|
writer.writeProperties("testProperties", getSettings());
|
||||||
|
|
||||||
clientThreadGroup = new ThreadGroup(getThreadGroupName());
|
clientThreadGroup = new ThreadGroup(getThreadGroupName());
|
||||||
for (int i=0; i<getNumClients(); i++) {
|
for (int i=0; i<getNumClients(); i++) {
|
||||||
|
@ -75,66 +80,7 @@ public abstract class JmsClientSystemSupport {
|
||||||
performanceSampler.startSampler();
|
performanceSampler.startSampler();
|
||||||
performanceSampler.waitForSamplerToFinish(0);
|
performanceSampler.waitForSamplerToFinish(0);
|
||||||
|
|
||||||
report.stopGenerateReport();
|
writer.closeReportWriter();
|
||||||
}
|
|
||||||
|
|
||||||
protected void distributeDestinations(String distroType, int clientIndex, int numClients, int numDests, Properties clientSettings) {
|
|
||||||
if (distroType.equalsIgnoreCase(DEST_DISTRO_ALL)) {
|
|
||||||
clientSettings.setProperty(KEY_CLIENT_DEST_COUNT, String.valueOf(numDests));
|
|
||||||
clientSettings.setProperty(KEY_CLIENT_DEST_INDEX, "0");
|
|
||||||
} else if (distroType.equalsIgnoreCase(DEST_DISTRO_EQUAL)) {
|
|
||||||
int destPerClient = (numDests / numClients);
|
|
||||||
// There are equal or more destinations per client
|
|
||||||
if (destPerClient > 0) {
|
|
||||||
clientSettings.setProperty(KEY_CLIENT_DEST_COUNT, String.valueOf(destPerClient));
|
|
||||||
clientSettings.setProperty(KEY_CLIENT_DEST_INDEX, String.valueOf(destPerClient * clientIndex));
|
|
||||||
|
|
||||||
// If there are more clients than destinations, share destinations per client
|
|
||||||
} else {
|
|
||||||
clientSettings.setProperty(KEY_CLIENT_DEST_COUNT, "1"); // At most one destination per client
|
|
||||||
clientSettings.setProperty(KEY_CLIENT_DEST_INDEX, String.valueOf(clientIndex % numDests));
|
|
||||||
}
|
|
||||||
} else if (distroType.equalsIgnoreCase(DEST_DISTRO_DIVIDE)) {
|
|
||||||
int destPerClient = (numDests / numClients);
|
|
||||||
// There are equal or more destinations per client
|
|
||||||
if (destPerClient > 0) {
|
|
||||||
int remain = numDests % numClients;
|
|
||||||
int nextIndex;
|
|
||||||
if (clientIndex < remain) {
|
|
||||||
destPerClient++;
|
|
||||||
nextIndex = clientIndex * destPerClient;
|
|
||||||
} else {
|
|
||||||
nextIndex = (clientIndex * destPerClient) + remain;
|
|
||||||
}
|
|
||||||
|
|
||||||
clientSettings.setProperty(KEY_CLIENT_DEST_COUNT, String.valueOf(destPerClient));
|
|
||||||
clientSettings.setProperty(KEY_CLIENT_DEST_INDEX, String.valueOf(nextIndex));
|
|
||||||
|
|
||||||
// If there are more clients than destinations, share destinations per client
|
|
||||||
} else {
|
|
||||||
clientSettings.setProperty(KEY_CLIENT_DEST_COUNT, "1"); // At most one destination per client
|
|
||||||
clientSettings.setProperty(KEY_CLIENT_DEST_INDEX, String.valueOf(clientIndex % numDests));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send to all for unknown behavior
|
|
||||||
} else {
|
|
||||||
clientSettings.setProperty(KEY_CLIENT_DEST_COUNT, String.valueOf(numDests));
|
|
||||||
clientSettings.setProperty(KEY_CLIENT_DEST_INDEX, "0");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void runJmsClient(String clientName, Properties clientSettings);
|
|
||||||
|
|
||||||
public String getClientName() {
|
|
||||||
return "JMS Client: ";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getThreadName() {
|
|
||||||
return "JMS Client Thread: ";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getThreadGroupName() {
|
|
||||||
return "JMS Clients Thread Group";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public PerfMeasurementTool getPerformanceSampler() {
|
public PerfMeasurementTool getPerformanceSampler() {
|
||||||
|
@ -228,4 +174,102 @@ public abstract class JmsClientSystemSupport {
|
||||||
public void setTotalDests(int totalDests) {
|
public void setTotalDests(int totalDests) {
|
||||||
this.totalDests = totalDests;
|
this.totalDests = totalDests;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getReportName() {
|
||||||
|
if (reportName == null) {
|
||||||
|
return "clientPerformanceReport.xml";
|
||||||
|
} else {
|
||||||
|
return reportName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReportName(String reportName) {
|
||||||
|
this.reportName = reportName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClientName() {
|
||||||
|
if (clientName == null) {
|
||||||
|
return "JMS Client: ";
|
||||||
|
} else {
|
||||||
|
return clientName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientName(String clientName) {
|
||||||
|
this.clientName = clientName;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PerformanceReportWriter createPerfWriter() {
|
||||||
|
if (reportType.equalsIgnoreCase(REPORT_XML_FILE)) {
|
||||||
|
return new XmlFilePerfReportWriter(getReportDirectory(), getReportName());
|
||||||
|
} else if (reportType.equalsIgnoreCase(REPORT_VERBOSE)) {
|
||||||
|
return new VerbosePerfReportWriter();
|
||||||
|
} else {
|
||||||
|
// Use verbose if unknown report type
|
||||||
|
return new VerbosePerfReportWriter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void distributeDestinations(String distroType, int clientIndex, int numClients, int numDests, Properties clientSettings) {
|
||||||
|
if (distroType.equalsIgnoreCase(DEST_DISTRO_ALL)) {
|
||||||
|
clientSettings.setProperty(getDestCountKey(), String.valueOf(numDests));
|
||||||
|
clientSettings.setProperty(getDestIndexKey(), "0");
|
||||||
|
} else if (distroType.equalsIgnoreCase(DEST_DISTRO_EQUAL)) {
|
||||||
|
int destPerClient = (numDests / numClients);
|
||||||
|
// There are equal or more destinations per client
|
||||||
|
if (destPerClient > 0) {
|
||||||
|
clientSettings.setProperty(getDestCountKey(), String.valueOf(destPerClient));
|
||||||
|
clientSettings.setProperty(getDestIndexKey(), String.valueOf(destPerClient * clientIndex));
|
||||||
|
|
||||||
|
// If there are more clients than destinations, share destinations per client
|
||||||
|
} else {
|
||||||
|
clientSettings.setProperty(getDestCountKey(), "1"); // At most one destination per client
|
||||||
|
clientSettings.setProperty(getDestIndexKey(), String.valueOf(clientIndex % numDests));
|
||||||
|
}
|
||||||
|
} else if (distroType.equalsIgnoreCase(DEST_DISTRO_DIVIDE)) {
|
||||||
|
int destPerClient = (numDests / numClients);
|
||||||
|
// There are equal or more destinations per client
|
||||||
|
if (destPerClient > 0) {
|
||||||
|
int remain = numDests % numClients;
|
||||||
|
int nextIndex;
|
||||||
|
if (clientIndex < remain) {
|
||||||
|
destPerClient++;
|
||||||
|
nextIndex = clientIndex * destPerClient;
|
||||||
|
} else {
|
||||||
|
nextIndex = (clientIndex * destPerClient) + remain;
|
||||||
|
}
|
||||||
|
|
||||||
|
clientSettings.setProperty(getDestCountKey(), String.valueOf(destPerClient));
|
||||||
|
clientSettings.setProperty(getDestIndexKey(), String.valueOf(nextIndex));
|
||||||
|
|
||||||
|
// If there are more clients than destinations, share destinations per client
|
||||||
|
} else {
|
||||||
|
clientSettings.setProperty(getDestCountKey(), "1"); // At most one destination per client
|
||||||
|
clientSettings.setProperty(getDestIndexKey(), String.valueOf(clientIndex % numDests));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send to all for unknown behavior
|
||||||
|
} else {
|
||||||
|
clientSettings.setProperty(getDestCountKey(), String.valueOf(numDests));
|
||||||
|
clientSettings.setProperty(getDestIndexKey(), "0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void runJmsClient(String clientName, Properties clientSettings);
|
||||||
|
|
||||||
|
protected String getThreadName() {
|
||||||
|
return "JMS Client Thread: ";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getThreadGroupName() {
|
||||||
|
return "JMS Clients Thread Group";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getDestCountKey() {
|
||||||
|
return "client.destCount";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getDestIndexKey() {
|
||||||
|
return "client.destIndex";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,12 +20,30 @@ import javax.jms.JMSException;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
public class JmsConsumerSystem extends JmsClientSystemSupport {
|
public class JmsConsumerSystem extends JmsClientSystemSupport {
|
||||||
public void runJmsClient(String clientName, Properties clientSettings) {
|
|
||||||
|
public String getReportName() {
|
||||||
|
if (reportName == null) {
|
||||||
|
return "JmsConsumer_ClientCount" + getNumClients() + "_DestCount" + getTotalDests() + "_" + getDestDistro() + ".xml";
|
||||||
|
} else {
|
||||||
|
return reportName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClientName() {
|
||||||
|
if (clientName == null) {
|
||||||
|
return "JmsConsumer";
|
||||||
|
} else {
|
||||||
|
return clientName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void runJmsClient(String clientName, Properties clientSettings) {
|
||||||
PerfMeasurementTool sampler = getPerformanceSampler();
|
PerfMeasurementTool sampler = getPerformanceSampler();
|
||||||
|
|
||||||
JmsConsumerClient consumer = new JmsConsumerClient();
|
JmsConsumerClient consumer = new JmsConsumerClient();
|
||||||
consumer.setSettings(clientSettings);
|
consumer.setSettings(clientSettings);
|
||||||
consumer.setConsumerName(clientName); // For durable subscribers
|
consumer.setConsumerName(clientName); // For durable subscribers
|
||||||
|
consumer.setClientName(clientName);
|
||||||
|
|
||||||
if (sampler != null) {
|
if (sampler != null) {
|
||||||
sampler.registerClient(consumer);
|
sampler.registerClient(consumer);
|
||||||
|
@ -39,18 +57,22 @@ public class JmsConsumerSystem extends JmsClientSystemSupport {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getClientName() {
|
protected String getThreadName() {
|
||||||
return "JMS Consumer: ";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getThreadName() {
|
|
||||||
return "JMS Consumer Thread: ";
|
return "JMS Consumer Thread: ";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getThreadGroupName() {
|
protected String getThreadGroupName() {
|
||||||
return "JMS Consumer Thread Group";
|
return "JMS Consumer Thread Group";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected String getDestCountKey() {
|
||||||
|
return "consumer.destCount";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getDestIndexKey() {
|
||||||
|
return "consumer.destIndex";
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws JMSException {
|
public static void main(String[] args) throws JMSException {
|
||||||
Properties sysSettings = new Properties();
|
Properties sysSettings = new Properties();
|
||||||
for (int i = 0; i < args.length; i++) {
|
for (int i = 0; i < args.length; i++) {
|
||||||
|
|
|
@ -18,33 +18,22 @@ package org.apache.activemq.tool;
|
||||||
|
|
||||||
import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicLong;
|
import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
|
|
||||||
public class JmsPerformanceSupport extends JmsClientSupport implements PerfMeasurable {
|
public class JmsPerformanceSupport extends JmsClientSupport implements PerfMeasurable {
|
||||||
|
|
||||||
private static int clientCounter;
|
|
||||||
|
|
||||||
protected AtomicLong throughput = new AtomicLong(0);
|
protected AtomicLong throughput = new AtomicLong(0);
|
||||||
protected PerfEventListener listener = null;
|
protected PerfEventListener listener = null;
|
||||||
private int clientNumber;
|
protected String clientName = null;
|
||||||
|
|
||||||
public void reset() {
|
public void reset() {
|
||||||
setThroughput(0);
|
setThroughput(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized int getClientNumber() {
|
public String getClientName() {
|
||||||
if (clientNumber == 0) {
|
return clientName;
|
||||||
clientNumber = incrementClientCounter();
|
|
||||||
}
|
|
||||||
return clientNumber;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getClientName() {
|
public void setClientName(String clientName) {
|
||||||
try {
|
this.clientName = clientName;
|
||||||
return getConnection().getClientID();
|
|
||||||
} catch (JMSException e) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getThroughput() {
|
public long getThroughput() {
|
||||||
|
@ -70,8 +59,4 @@ public class JmsPerformanceSupport extends JmsClientSupport implements PerfMeasu
|
||||||
public PerfEventListener getPerfEventListener() {
|
public PerfEventListener getPerfEventListener() {
|
||||||
return listener;
|
return listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static synchronized int incrementClientCounter() {
|
|
||||||
return ++clientCounter;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,29 @@ import javax.jms.JMSException;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
public class JmsProducerSystem extends JmsClientSystemSupport {
|
public class JmsProducerSystem extends JmsClientSystemSupport {
|
||||||
public void runJmsClient(String clientName, Properties clientSettings) {
|
|
||||||
|
public String getReportName() {
|
||||||
|
if (reportName == null) {
|
||||||
|
return "JmsProducer_ClientCount" + getNumClients() + "_DestCount" + getTotalDests() + "_" + getDestDistro() + ".xml";
|
||||||
|
} else {
|
||||||
|
return reportName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClientName() {
|
||||||
|
if (clientName == null) {
|
||||||
|
return "JmsProducer";
|
||||||
|
} else {
|
||||||
|
return clientName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void runJmsClient(String clientName, Properties clientSettings) {
|
||||||
PerfMeasurementTool sampler = getPerformanceSampler();
|
PerfMeasurementTool sampler = getPerformanceSampler();
|
||||||
|
|
||||||
JmsProducerClient producer = new JmsProducerClient();
|
JmsProducerClient producer = new JmsProducerClient();
|
||||||
producer.setSettings(clientSettings);
|
producer.setSettings(clientSettings);
|
||||||
|
producer.setClientName(clientName);
|
||||||
|
|
||||||
if (sampler != null) {
|
if (sampler != null) {
|
||||||
sampler.registerClient(producer);
|
sampler.registerClient(producer);
|
||||||
|
@ -39,18 +57,22 @@ public class JmsProducerSystem extends JmsClientSystemSupport {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getClientName() {
|
protected String getThreadName() {
|
||||||
return "JMS Producer: ";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getThreadName() {
|
|
||||||
return "JMS Producer Thread: ";
|
return "JMS Producer Thread: ";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getThreadGroupName() {
|
protected String getThreadGroupName() {
|
||||||
return "JMS Producer Thread Group";
|
return "JMS Producer Thread Group";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected String getDestCountKey() {
|
||||||
|
return "producer.destCount";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getDestIndexKey() {
|
||||||
|
return "producer.destIndex";
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
Properties sysSettings = new Properties();
|
Properties sysSettings = new Properties();
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@ import java.util.Properties;
|
||||||
|
|
||||||
public interface PerfMeasurable {
|
public interface PerfMeasurable {
|
||||||
public void reset();
|
public void reset();
|
||||||
public int getClientNumber();
|
|
||||||
public String getClientName();
|
public String getClientName();
|
||||||
public long getThroughput();
|
public long getThroughput();
|
||||||
public Properties getSettings();
|
public Properties getSettings();
|
||||||
|
|
|
@ -19,12 +19,13 @@ package org.apache.activemq.tool;
|
||||||
import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
|
import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import javax.jms.JMSException;
|
import javax.jms.JMSException;
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.apache.activemq.tool.reports.PerformanceReportWriter;
|
||||||
|
|
||||||
public class PerfMeasurementTool implements PerfEventListener, Runnable {
|
public class PerfMeasurementTool implements PerfEventListener, Runnable {
|
||||||
public static final String PREFIX_CONFIG_SYSTEM_TEST = "sampler.";
|
public static final String PREFIX_CONFIG_SYSTEM_TEST = "sampler.";
|
||||||
|
|
||||||
|
@ -37,7 +38,7 @@ public class PerfMeasurementTool implements PerfEventListener, Runnable {
|
||||||
private AtomicBoolean start = new AtomicBoolean(false);
|
private AtomicBoolean start = new AtomicBoolean(false);
|
||||||
private AtomicBoolean stop = new AtomicBoolean(false);
|
private AtomicBoolean stop = new AtomicBoolean(false);
|
||||||
private AtomicBoolean isRunning = new AtomicBoolean(false);
|
private AtomicBoolean isRunning = new AtomicBoolean(false);
|
||||||
private PrintWriter writer = null;
|
private PerformanceReportWriter perfWriter = null;
|
||||||
private Properties samplerSettings = new Properties();
|
private Properties samplerSettings = new Properties();
|
||||||
|
|
||||||
private List perfClients = new ArrayList();
|
private List perfClients = new ArrayList();
|
||||||
|
@ -62,12 +63,12 @@ public class PerfMeasurementTool implements PerfEventListener, Runnable {
|
||||||
ReflectionUtil.configureClass(this, samplerSettings);
|
ReflectionUtil.configureClass(this, samplerSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PrintWriter getWriter() {
|
public PerformanceReportWriter getPerfWriter() {
|
||||||
return writer;
|
return perfWriter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setWriter(PrintWriter writer) {
|
public void setPerfWriter(PerformanceReportWriter writer) {
|
||||||
this.writer = writer;
|
this.perfWriter = writer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getDuration() {
|
public long getDuration() {
|
||||||
|
@ -169,8 +170,9 @@ public class PerfMeasurementTool implements PerfEventListener, Runnable {
|
||||||
public void sampleClients() {
|
public void sampleClients() {
|
||||||
for (Iterator i = perfClients.iterator(); i.hasNext();) {
|
for (Iterator i = perfClients.iterator(); i.hasNext();) {
|
||||||
PerfMeasurable client = (PerfMeasurable) i.next();
|
PerfMeasurable client = (PerfMeasurable) i.next();
|
||||||
getWriter().println("<sample index='" + sampleIndex + "' clientNumber='" + client.getClientNumber()
|
if (perfWriter != null) {
|
||||||
+ "' name='" + client.getClientName() + "' throughput='" + client.getThroughput() + "'/>");
|
perfWriter.writePerfData("index=" + sampleIndex + ",clientName=" + client.getClientName() + ",throughput=" + client.getThroughput());
|
||||||
|
}
|
||||||
client.reset();
|
client.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,165 +0,0 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Copyright 2005-2006 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.apache.activemq.tool;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
public class PerfReportGenerator {
|
|
||||||
|
|
||||||
private String reportDirectory = null;
|
|
||||||
private String reportName = null;
|
|
||||||
private PrintWriter writer = null;
|
|
||||||
|
|
||||||
private Properties testSettings;
|
|
||||||
|
|
||||||
public PerfReportGenerator() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public PerfReportGenerator(String reportDirectory, String reportName) {
|
|
||||||
this.setReportDirectory(reportDirectory);
|
|
||||||
this.setReportName(reportName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startGenerateReport() {
|
|
||||||
|
|
||||||
setReportDirectory(this.getTestSettings().getProperty("sysTest.reportDirectory", ""));
|
|
||||||
|
|
||||||
|
|
||||||
File reportDir = new File(getReportDirectory());
|
|
||||||
|
|
||||||
// Create output directory if it doesn't exist.
|
|
||||||
if (!reportDir.exists()) {
|
|
||||||
reportDir.mkdirs();
|
|
||||||
}
|
|
||||||
|
|
||||||
File reportFile = null;
|
|
||||||
if (reportDir != null) {
|
|
||||||
String filename = (this.getReportName()).substring(this.getReportName().lastIndexOf(".") + 1) + "-" + createReportName(getTestSettings());
|
|
||||||
reportFile = new File(this.getReportDirectory() + File.separator + filename + ".xml");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
this.writer = new PrintWriter(new FileOutputStream(reportFile));
|
|
||||||
addTestInformation(getWriter());
|
|
||||||
} catch (IOException e1) {
|
|
||||||
e1.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stopGenerateReport() {
|
|
||||||
this.getWriter().println("</test-result>");
|
|
||||||
this.getWriter().println("</test-report>");
|
|
||||||
this.getWriter().flush();
|
|
||||||
this.getWriter().close();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addTestInformation(PrintWriter writer) {
|
|
||||||
|
|
||||||
writer.println("<test-report>");
|
|
||||||
writer.println("<test-information>");
|
|
||||||
|
|
||||||
Enumeration keys;
|
|
||||||
String key;
|
|
||||||
|
|
||||||
// Add system property settings
|
|
||||||
writer.println("<system-settings>");
|
|
||||||
|
|
||||||
Properties sysProp = System.getProperties();
|
|
||||||
keys = sysProp.keys();
|
|
||||||
|
|
||||||
while (keys.hasMoreElements()) {
|
|
||||||
key = (String) keys.nextElement();
|
|
||||||
writer.println("<" + key + ">" + System.getProperty(key) + "</" + key + ">");
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.println("</system-settings>");
|
|
||||||
|
|
||||||
// Add client property settings
|
|
||||||
writer.println("<client-settings>");
|
|
||||||
|
|
||||||
if (this.getTestSettings() != null) {
|
|
||||||
keys = getTestSettings().propertyNames();
|
|
||||||
|
|
||||||
while (keys.hasMoreElements()) {
|
|
||||||
key = (String) keys.nextElement();
|
|
||||||
writer.println("<" + key + ">" + getTestSettings().get(key) + "</" + key + ">");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
writer.println("</client-settings>");
|
|
||||||
|
|
||||||
writer.println("</test-information>");
|
|
||||||
writer.println("<test-result>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public PrintWriter getWriter() {
|
|
||||||
return this.writer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getReportDirectory() {
|
|
||||||
return reportDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setReportDirectory(String reportDirectory) {
|
|
||||||
this.reportDirectory = reportDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getReportName() {
|
|
||||||
return reportName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String createReportName(Properties testSettings) {
|
|
||||||
if (testSettings != null) {
|
|
||||||
String[] keys = {"client.destCount", "client.asyncRecv", "client.durable",
|
|
||||||
"client.messageSize", "sysTest.numClients", "sysTest.totalDests"};
|
|
||||||
|
|
||||||
StringBuffer buffer = new StringBuffer();
|
|
||||||
String key;
|
|
||||||
String val;
|
|
||||||
String temp;
|
|
||||||
for (int i = 0; i < keys.length; i++) {
|
|
||||||
key = keys[i];
|
|
||||||
val = testSettings.getProperty(key);
|
|
||||||
|
|
||||||
if (val == null) continue;
|
|
||||||
|
|
||||||
temp = key.substring(key.indexOf(".") + 1);
|
|
||||||
buffer.append(temp + val);
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setReportName(String reportName) {
|
|
||||||
this.reportName = reportName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Properties getTestSettings() {
|
|
||||||
return testSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTestSettings(Properties testSettings) {
|
|
||||||
this.testSettings = testSettings;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,189 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2005-2006 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.activemq.tool.reports;
|
||||||
|
|
||||||
|
import org.apache.activemq.tool.ReflectionUtil;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
public abstract class AbstractPerfReportWriter implements PerformanceReportWriter {
|
||||||
|
public static final String KEY_SYS_TOTAL_TP = "SystemTotalTP";
|
||||||
|
public static final String KEY_SYS_TOTAL_CLIENTS = "SystemTotalClients";
|
||||||
|
public static final String KEY_SYS_AVE_TP = "SystemAveTP";
|
||||||
|
public static final String KEY_SYS_AVE_EMM_TP = "SystemAveEMMTP";
|
||||||
|
public static final String KEY_MIN_CLIENT_TP = "MinClientTP";
|
||||||
|
public static final String KEY_MAX_CLIENT_TP = "MaxClientTP";
|
||||||
|
public static final String KEY_MIN_CLIENT_TOTAL_TP = "MinClientTotalTP";
|
||||||
|
public static final String KEY_MAX_CLIENT_TOTAL_TP = "MaxClientTotalTP";
|
||||||
|
public static final String KEY_MIN_CLIENT_AVE_TP = "MinClientAveTP";
|
||||||
|
public static final String KEY_MAX_CLIENT_AVE_TP = "MaxClientAveTP";
|
||||||
|
public static final String KEY_MIN_CLIENT_AVE_EMM_TP = "MinClientAveEMMTP";
|
||||||
|
public static final String KEY_MAX_CLIENT_AVE_EMM_TP = "MaxClientAveEMMTP";
|
||||||
|
|
||||||
|
protected Properties settings;
|
||||||
|
protected Map clientThroughputs = new HashMap();
|
||||||
|
|
||||||
|
public void setSettings(Properties settings) {
|
||||||
|
this.settings = settings;
|
||||||
|
ReflectionUtil.configureClass(this, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Properties getSettings() {
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void parsePerfCsvData(String csvData) {
|
||||||
|
StringTokenizer tokenizer = new StringTokenizer(csvData, ",");
|
||||||
|
String data, key, val, clientName = null;
|
||||||
|
Long throughput = null;
|
||||||
|
while (tokenizer.hasMoreTokens()) {
|
||||||
|
data = tokenizer.nextToken();
|
||||||
|
key = data.substring(0, data.indexOf("="));
|
||||||
|
val = data.substring(data.indexOf("=") + 1);
|
||||||
|
|
||||||
|
if (key.equalsIgnoreCase("clientName")) {
|
||||||
|
clientName = val;
|
||||||
|
} else if (key.equalsIgnoreCase("throughput")) {
|
||||||
|
throughput = Long.valueOf(val);
|
||||||
|
} else {
|
||||||
|
// Ignore unknown token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addToClientTPList(clientName, throughput);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addToClientTPList(String clientName, Long throughput) {
|
||||||
|
// Write to client's throughput list
|
||||||
|
if (clientName == null || throughput == null) {
|
||||||
|
throw new IllegalArgumentException("Invalid Throughput CSV Data: clientName=" + clientName + ", throughput=" + throughput);
|
||||||
|
}
|
||||||
|
|
||||||
|
List clientTPList = (List)clientThroughputs.get(clientName);
|
||||||
|
if (clientTPList == null) {
|
||||||
|
clientTPList = new ArrayList();
|
||||||
|
clientThroughputs.put(clientName, clientTPList);
|
||||||
|
}
|
||||||
|
clientTPList.add(throughput);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Map createPerfSummary(Map clientTPMap) {
|
||||||
|
long minClientTP = Long.MAX_VALUE, // TP = throughput
|
||||||
|
maxClientTP = Long.MIN_VALUE,
|
||||||
|
minClientTotalTP = Long.MAX_VALUE,
|
||||||
|
maxClientTotalTP = Long.MIN_VALUE,
|
||||||
|
systemTotalTP = 0;
|
||||||
|
|
||||||
|
double minClientAveTP = Double.MAX_VALUE,
|
||||||
|
maxClientAveTP = Double.MIN_VALUE,
|
||||||
|
minClientAveEMMTP = Double.MAX_VALUE, // EMM = Excluding Min/Max
|
||||||
|
maxClientAveEMMTP = Double.MIN_VALUE,
|
||||||
|
systemAveTP = 0.0,
|
||||||
|
systemAveEMMTP = 0.0;
|
||||||
|
|
||||||
|
String nameMinClientTP = "",
|
||||||
|
nameMaxClientTP = "",
|
||||||
|
nameMinClientTotalTP = "",
|
||||||
|
nameMaxClientTotalTP = "",
|
||||||
|
nameMinClientAveTP = "",
|
||||||
|
nameMaxClientAveTP = "",
|
||||||
|
nameMinClientAveEMMTP = "",
|
||||||
|
nameMaxClientAveEMMTP = "";
|
||||||
|
|
||||||
|
Set clientNames = clientTPMap.keySet();
|
||||||
|
String clientName;
|
||||||
|
List clientTPList;
|
||||||
|
long tempLong;
|
||||||
|
double tempDouble;
|
||||||
|
int clientCount = 0;
|
||||||
|
for (Iterator i=clientNames.iterator(); i.hasNext();) {
|
||||||
|
clientName = (String)i.next();
|
||||||
|
clientTPList = (List)clientTPMap.get(clientName);
|
||||||
|
clientCount++;
|
||||||
|
|
||||||
|
tempLong = PerformanceStatisticsUtil.getMinThroughput(clientTPList);
|
||||||
|
if (tempLong < minClientTP) {
|
||||||
|
minClientTP = tempLong;
|
||||||
|
nameMinClientTP = clientName;
|
||||||
|
}
|
||||||
|
|
||||||
|
tempLong = PerformanceStatisticsUtil.getMaxThroughput(clientTPList);
|
||||||
|
if (tempLong > maxClientTP) {
|
||||||
|
maxClientTP = tempLong;
|
||||||
|
nameMaxClientTP = clientName;
|
||||||
|
}
|
||||||
|
|
||||||
|
tempLong = PerformanceStatisticsUtil.getTotalThroughput(clientTPList);
|
||||||
|
systemTotalTP += tempLong; // Accumulate total TP
|
||||||
|
if (tempLong < minClientTotalTP) {
|
||||||
|
minClientTotalTP = tempLong;
|
||||||
|
nameMinClientTotalTP = clientName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tempLong > maxClientTotalTP) {
|
||||||
|
maxClientTotalTP = tempLong;
|
||||||
|
nameMaxClientTotalTP = clientName;
|
||||||
|
}
|
||||||
|
|
||||||
|
tempDouble = PerformanceStatisticsUtil.getAveThroughput(clientTPList);
|
||||||
|
systemAveTP += tempDouble; // Accumulate ave throughput
|
||||||
|
if (tempDouble < minClientAveTP) {
|
||||||
|
minClientAveTP = tempDouble;
|
||||||
|
nameMinClientAveTP = clientName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tempDouble > maxClientAveTP) {
|
||||||
|
maxClientAveTP = tempDouble;
|
||||||
|
nameMaxClientAveTP = clientName;
|
||||||
|
}
|
||||||
|
|
||||||
|
tempDouble = PerformanceStatisticsUtil.getAveThroughputExcludingMinMax(clientTPList);
|
||||||
|
systemAveEMMTP += tempDouble; // Accumulate ave throughput excluding min/max
|
||||||
|
if (tempDouble < minClientAveEMMTP) {
|
||||||
|
minClientAveEMMTP = tempDouble;
|
||||||
|
nameMinClientAveEMMTP = clientName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tempDouble > maxClientAveEMMTP) {
|
||||||
|
maxClientAveEMMTP = tempDouble;
|
||||||
|
nameMaxClientAveEMMTP = clientName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map summary = new HashMap();
|
||||||
|
summary.put(KEY_SYS_TOTAL_TP, String.valueOf(systemTotalTP));
|
||||||
|
summary.put(KEY_SYS_TOTAL_CLIENTS, String.valueOf(clientCount));
|
||||||
|
summary.put(KEY_SYS_AVE_TP, String.valueOf(systemAveTP));
|
||||||
|
summary.put(KEY_SYS_AVE_EMM_TP, String.valueOf(systemAveEMMTP));
|
||||||
|
summary.put(KEY_MIN_CLIENT_TP, nameMinClientTP + "=" + minClientTP);
|
||||||
|
summary.put(KEY_MAX_CLIENT_TP, nameMaxClientTP + "=" + maxClientTP);
|
||||||
|
summary.put(KEY_MIN_CLIENT_TOTAL_TP, nameMinClientTotalTP + "=" + minClientTotalTP);
|
||||||
|
summary.put(KEY_MAX_CLIENT_TOTAL_TP, nameMaxClientTotalTP + "=" + maxClientTotalTP);
|
||||||
|
summary.put(KEY_MIN_CLIENT_AVE_TP, nameMinClientAveTP + "=" + minClientAveTP);
|
||||||
|
summary.put(KEY_MAX_CLIENT_AVE_TP, nameMaxClientAveTP + "=" + maxClientAveTP);
|
||||||
|
summary.put(KEY_MIN_CLIENT_AVE_EMM_TP, nameMinClientAveEMMTP + "=" + minClientAveEMMTP);
|
||||||
|
summary.put(KEY_MAX_CLIENT_AVE_EMM_TP, nameMaxClientAveEMMTP + "=" + maxClientAveEMMTP);
|
||||||
|
|
||||||
|
return summary;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2005-2006 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.activemq.tool.reports;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
public interface PerformanceReportWriter {
|
||||||
|
public void setSettings(Properties settings);
|
||||||
|
public Properties getSettings();
|
||||||
|
public void openReportWriter();
|
||||||
|
public void closeReportWriter();
|
||||||
|
public void writeInfo(String info);
|
||||||
|
public void writePerfData(String data);
|
||||||
|
public void writeProperties(String header, Properties props);
|
||||||
|
public void writeProperties(Properties props);
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2005-2006 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.activemq.tool.reports;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
public final class PerformanceStatisticsUtil {
|
||||||
|
private PerformanceStatisticsUtil() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long getTotalThroughput(List totalTPList) {
|
||||||
|
long totalTP = 0;
|
||||||
|
if (totalTPList != null) {
|
||||||
|
for (Iterator i=totalTPList.iterator(); i.hasNext();) {
|
||||||
|
totalTP += ((Long)i.next()).longValue();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
totalTP = -1;
|
||||||
|
}
|
||||||
|
return totalTP;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long getMinThroughput(List totalTPList) {
|
||||||
|
long minTP = Long.MAX_VALUE;
|
||||||
|
if (totalTPList != null) {
|
||||||
|
for (Iterator i=totalTPList.iterator(); i.hasNext();) {
|
||||||
|
minTP = Math.min(((Long)i.next()).longValue(), minTP);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
minTP = -1;
|
||||||
|
}
|
||||||
|
return minTP;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long getMaxThroughput(List totalTPList) {
|
||||||
|
long maxTP = Long.MIN_VALUE;
|
||||||
|
if (totalTPList != null) {
|
||||||
|
for (Iterator i=totalTPList.iterator(); i.hasNext();) {
|
||||||
|
maxTP = Math.max(((Long)i.next()).longValue(), maxTP);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
maxTP = -1;
|
||||||
|
}
|
||||||
|
return maxTP;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getAveThroughput(List totalTPList) {
|
||||||
|
double aveTP;
|
||||||
|
if (totalTPList != null) {
|
||||||
|
int sampleCount = 0;
|
||||||
|
long totalTP = 0;
|
||||||
|
for (Iterator i=totalTPList.iterator(); i.hasNext();) {
|
||||||
|
sampleCount++;
|
||||||
|
totalTP += ((Long)i.next()).longValue();
|
||||||
|
}
|
||||||
|
return (double)totalTP / (double)sampleCount;
|
||||||
|
} else {
|
||||||
|
aveTP = -1;
|
||||||
|
}
|
||||||
|
return aveTP;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getAveThroughputExcludingMinMax(List totalTPList) {
|
||||||
|
double aveTP;
|
||||||
|
long minTP = getMinThroughput(totalTPList);
|
||||||
|
long maxTP = getMaxThroughput(totalTPList);
|
||||||
|
if (totalTPList != null) {
|
||||||
|
int sampleCount = 0;
|
||||||
|
long totalTP = 0;
|
||||||
|
long sampleTP;
|
||||||
|
for (Iterator i=totalTPList.iterator(); i.hasNext();) {
|
||||||
|
sampleCount++;
|
||||||
|
sampleTP = ((Long)i.next()).longValue();
|
||||||
|
if (sampleTP != minTP && sampleTP != maxTP) {
|
||||||
|
totalTP += sampleTP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (double)totalTP / (double)sampleCount;
|
||||||
|
} else {
|
||||||
|
aveTP = -1;
|
||||||
|
}
|
||||||
|
return aveTP;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2005-2006 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.activemq.tool.reports;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class VerbosePerfReportWriter extends AbstractPerfReportWriter {
|
||||||
|
|
||||||
|
public void openReportWriter() {
|
||||||
|
writeProperties("System Properties", System.getProperties());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeReportWriter() {
|
||||||
|
writeHeader("Performance Summary");
|
||||||
|
writePerfSummary();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeInfo(String info) {
|
||||||
|
System.out.println("[PERF-INFO]: " + info);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeHeader(String header) {
|
||||||
|
char[] border = new char[header.length() + 8]; // +8 for spacing
|
||||||
|
Arrays.fill(border, '#');
|
||||||
|
String borderStr = new String(border);
|
||||||
|
|
||||||
|
System.out.println(borderStr);
|
||||||
|
System.out.println("# " + header + " #");
|
||||||
|
System.out.println(borderStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writePerfData(String data) {
|
||||||
|
System.out.println("[PERF-DATA]: " + data);
|
||||||
|
// Assume data is a CSV of key-value pair
|
||||||
|
parsePerfCsvData(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeProperties(String header, Properties props) {
|
||||||
|
writeHeader(header);
|
||||||
|
writeProperties(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeProperties(Properties props) {
|
||||||
|
for (Iterator i=props.keySet().iterator(); i.hasNext();) {
|
||||||
|
String key = (String)i.next();
|
||||||
|
String val = props.getProperty(key, "");
|
||||||
|
System.out.println("[PERF-PROP]: " + key + "=" + val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writePerfSummary() {
|
||||||
|
Map summary = createPerfSummary(clientThroughputs);
|
||||||
|
|
||||||
|
System.out.println("[PERF-SUMMARY] System Total Throughput: " + summary.get(KEY_SYS_TOTAL_TP));
|
||||||
|
System.out.println("[PERF-SUMMARY] System Total Clients: " + summary.get(KEY_SYS_TOTAL_CLIENTS));
|
||||||
|
System.out.println("[PERF-SUMMARY] System Average Throughput: " + summary.get(KEY_SYS_AVE_TP));
|
||||||
|
System.out.println("[PERF-SUMMARY] System Average Throughput Excluding Min/Max: " + summary.get(KEY_SYS_AVE_EMM_TP));
|
||||||
|
System.out.println("[PERF-SUMMARY] Min Client Throughput Per Sample: " + summary.get(KEY_MIN_CLIENT_TP));
|
||||||
|
System.out.println("[PERF-SUMMARY] Max Client Throughput Per Sample: " + summary.get(KEY_MAX_CLIENT_TP));
|
||||||
|
System.out.println("[PERF-SUMMARY] Min Client Total Throughput: " + summary.get(KEY_MIN_CLIENT_TOTAL_TP));
|
||||||
|
System.out.println("[PERF-SUMMARY] Max Client Total Throughput: " + summary.get(KEY_MAX_CLIENT_TOTAL_TP));
|
||||||
|
System.out.println("[PERF-SUMMARY] Min Client Average Throughput: " + summary.get(KEY_MIN_CLIENT_AVE_TP));
|
||||||
|
System.out.println("[PERF-SUMMARY] Max Client Average Throughput: " + summary.get(KEY_MAX_CLIENT_AVE_TP));
|
||||||
|
System.out.println("[PERF-SUMMARY] Min Client Average Throughput Excluding Min/Max: " + summary.get(KEY_MIN_CLIENT_AVE_EMM_TP));
|
||||||
|
System.out.println("[PERF-SUMMARY] Max Client Average Throughput Excluding Min/Max: " + summary.get(KEY_MAX_CLIENT_AVE_EMM_TP));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,312 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2005-2006 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.activemq.tool.reports;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class XmlFilePerfReportWriter extends AbstractPerfReportWriter {
|
||||||
|
private static final Log log = LogFactory.getLog(XmlFilePerfReportWriter.class);
|
||||||
|
|
||||||
|
private File tempLogFile;
|
||||||
|
private PrintWriter tempLogFileWriter;
|
||||||
|
|
||||||
|
private File xmlFile;
|
||||||
|
private PrintWriter xmlFileWriter;
|
||||||
|
|
||||||
|
private String reportDir;
|
||||||
|
private String reportName;
|
||||||
|
|
||||||
|
private Map testPropsMap;
|
||||||
|
private List testPropsList;
|
||||||
|
|
||||||
|
public XmlFilePerfReportWriter() {
|
||||||
|
this("", "PerformanceReport.xml");
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmlFilePerfReportWriter(String reportDir, String reportName) {
|
||||||
|
this.testPropsMap = new HashMap();
|
||||||
|
this.testPropsList = new ArrayList();
|
||||||
|
this.reportDir = reportDir;
|
||||||
|
this.reportName = reportName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void openReportWriter() {
|
||||||
|
if (tempLogFile == null) {
|
||||||
|
tempLogFile = createTempLogFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Disable auto-flush and allocate 100kb of buffer
|
||||||
|
tempLogFileWriter = new PrintWriter(new BufferedOutputStream(new FileOutputStream(tempLogFile), 102400), false);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeReportWriter() {
|
||||||
|
// Flush and close log file writer
|
||||||
|
tempLogFileWriter.flush();
|
||||||
|
tempLogFileWriter.close();
|
||||||
|
|
||||||
|
writeToXml();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReportDir() {
|
||||||
|
return reportDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReportDir(String reportDir) {
|
||||||
|
this.reportDir = reportDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReportName() {
|
||||||
|
return reportName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReportName(String reportName) {
|
||||||
|
this.reportName = reportName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeInfo(String info) {
|
||||||
|
tempLogFileWriter.println("[INFO]" + info);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writePerfData(String data) {
|
||||||
|
tempLogFileWriter.println("[DATA]" + data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeProperties(String header, Properties props) {
|
||||||
|
testPropsMap.put(header, props);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeProperties(Properties props) {
|
||||||
|
testPropsList.add(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected File createTempLogFile() {
|
||||||
|
File f = null;
|
||||||
|
try {
|
||||||
|
f = File.createTempFile("tmpPL", null);
|
||||||
|
} catch (IOException e) {
|
||||||
|
f = new File("tmpPL" + System.currentTimeMillis() + ".tmp");
|
||||||
|
}
|
||||||
|
f.deleteOnExit();
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected File createXmlFile() {
|
||||||
|
String filename = (getReportName().endsWith(".xml") ? getReportName() : (getReportName() + ".xml"));
|
||||||
|
String path = (getReportDir() == null) ? "" : getReportDir();
|
||||||
|
|
||||||
|
File f = new File(path + filename);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void writeToXml() {
|
||||||
|
try {
|
||||||
|
xmlFile = createXmlFile();
|
||||||
|
xmlFileWriter = new PrintWriter(new FileOutputStream(xmlFile));
|
||||||
|
writeXmlHeader();
|
||||||
|
writeXmlTestSettings();
|
||||||
|
writeXmlLogFile();
|
||||||
|
writeXmlPerfSummary();
|
||||||
|
writeXmlFooter();
|
||||||
|
xmlFileWriter.close();
|
||||||
|
|
||||||
|
System.out.println("Created performance report: " + xmlFile.getAbsolutePath());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void writeXmlHeader() {
|
||||||
|
xmlFileWriter.println("<testResult>");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void writeXmlFooter() {
|
||||||
|
xmlFileWriter.println("</testResult>");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void writeXmlTestSettings() {
|
||||||
|
Properties props;
|
||||||
|
// Write system settings
|
||||||
|
writeMap("systemSettings", System.getProperties());
|
||||||
|
|
||||||
|
// Write test settings
|
||||||
|
for (Iterator i=testPropsMap.keySet().iterator(); i.hasNext();) {
|
||||||
|
String key = (String)i.next();
|
||||||
|
props = (Properties)testPropsMap.get(key);
|
||||||
|
writeMap(key, props);
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = 1;
|
||||||
|
for (Iterator i=testPropsList.iterator(); i.hasNext();) {
|
||||||
|
props = (Properties)i.next();
|
||||||
|
writeMap("settings" + count++, props);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void writeXmlLogFile() throws IOException {
|
||||||
|
// Write throughput data
|
||||||
|
xmlFileWriter.println("<property name='performanceData'>");
|
||||||
|
xmlFileWriter.println("<list>");
|
||||||
|
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(tempLogFile)));
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
if (line.startsWith("[DATA]")) {
|
||||||
|
parsePerfCsvData(line.substring("[DATA]".length()));
|
||||||
|
} else if (line.startsWith("[INFO]")) {
|
||||||
|
xmlFileWriter.println("<value>" + line + "</value>");
|
||||||
|
} else {
|
||||||
|
xmlFileWriter.println("<value>[ERROR]" + line + "</value>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlFileWriter.println("</list>");
|
||||||
|
xmlFileWriter.println("</property>");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void writeXmlPerfSummary() {
|
||||||
|
Map summary = createPerfSummary(clientThroughputs);
|
||||||
|
|
||||||
|
xmlFileWriter.println("<property name='perfSummary'>");
|
||||||
|
xmlFileWriter.println("<props>");
|
||||||
|
|
||||||
|
String val, clientName, clientVal;
|
||||||
|
|
||||||
|
val = (String)summary.get(KEY_SYS_TOTAL_TP);
|
||||||
|
System.out.println("System Total Throughput: " + val);
|
||||||
|
xmlFileWriter.println("<prop key='" + KEY_SYS_TOTAL_TP + "'>" + val + "</prop>");
|
||||||
|
|
||||||
|
val = (String)summary.get(KEY_SYS_TOTAL_CLIENTS);
|
||||||
|
System.out.println("System Total Clients: " + val);
|
||||||
|
xmlFileWriter.println("<prop key='" + KEY_SYS_TOTAL_CLIENTS + "'>" + val + "</prop>");
|
||||||
|
|
||||||
|
val = (String)summary.get(KEY_SYS_AVE_TP);
|
||||||
|
System.out.println("System Average Throughput: " + val);
|
||||||
|
xmlFileWriter.println("<prop key='" + KEY_SYS_AVE_TP + "'>" + val + "</prop>");
|
||||||
|
|
||||||
|
val = (String)summary.get(KEY_SYS_AVE_EMM_TP);
|
||||||
|
System.out.println("System Average Throughput Excluding Min/Max: " + val);
|
||||||
|
xmlFileWriter.println("<prop key='" + KEY_SYS_AVE_EMM_TP + "'>" + val + "</prop>");
|
||||||
|
|
||||||
|
val = (String)summary.get(KEY_MIN_CLIENT_TP);
|
||||||
|
clientName = val.substring(0, val.indexOf("="));
|
||||||
|
clientVal = val.substring(val.indexOf("=") + 1);
|
||||||
|
System.out.println("Min Client Throughput Per Sample: clientName=" + clientName + ", value=" + clientVal);
|
||||||
|
xmlFileWriter.println("<prop key='" + KEY_MIN_CLIENT_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>");
|
||||||
|
|
||||||
|
val = (String)summary.get(KEY_MAX_CLIENT_TP);
|
||||||
|
clientName = val.substring(0, val.indexOf("="));
|
||||||
|
clientVal = val.substring(val.indexOf("=") + 1);
|
||||||
|
System.out.println("Max Client Throughput Per Sample: clientName=" + clientName + ", value=" + clientVal);
|
||||||
|
xmlFileWriter.println("<prop key='" + KEY_MAX_CLIENT_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>");
|
||||||
|
|
||||||
|
val = (String)summary.get(KEY_MIN_CLIENT_TOTAL_TP);
|
||||||
|
clientName = val.substring(0, val.indexOf("="));
|
||||||
|
clientVal = val.substring(val.indexOf("=") + 1);
|
||||||
|
System.out.println("Min Client Total Throughput: clientName=" + clientName + ", value=" + clientVal);
|
||||||
|
xmlFileWriter.println("<prop key='" + KEY_MIN_CLIENT_TOTAL_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>");
|
||||||
|
|
||||||
|
val = (String)summary.get(KEY_MAX_CLIENT_TOTAL_TP);
|
||||||
|
clientName = val.substring(0, val.indexOf("="));
|
||||||
|
clientVal = val.substring(val.indexOf("=") + 1);
|
||||||
|
System.out.println("Max Client Total Throughput: clientName=" + clientName + ", value=" + clientVal);
|
||||||
|
xmlFileWriter.println("<prop key='" + KEY_MAX_CLIENT_TOTAL_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>");
|
||||||
|
|
||||||
|
val = (String)summary.get(KEY_MIN_CLIENT_AVE_TP);
|
||||||
|
clientName = val.substring(0, val.indexOf("="));
|
||||||
|
clientVal = val.substring(val.indexOf("=") + 1);
|
||||||
|
System.out.println("Min Average Client Throughput: clientName=" + clientName + ", value=" + clientVal);
|
||||||
|
xmlFileWriter.println("<prop key='" + KEY_MIN_CLIENT_AVE_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>");
|
||||||
|
|
||||||
|
val = (String)summary.get(KEY_MAX_CLIENT_AVE_TP);
|
||||||
|
clientName = val.substring(0, val.indexOf("="));
|
||||||
|
clientVal = val.substring(val.indexOf("=") + 1);
|
||||||
|
System.out.println("Max Average Client Throughput: clientName=" + clientName + ", value=" + clientVal);
|
||||||
|
xmlFileWriter.println("<prop key='" + KEY_MAX_CLIENT_AVE_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>");
|
||||||
|
|
||||||
|
val = (String)summary.get(KEY_MIN_CLIENT_AVE_EMM_TP);
|
||||||
|
clientName = val.substring(0, val.indexOf("="));
|
||||||
|
clientVal = val.substring(val.indexOf("=") + 1);
|
||||||
|
System.out.println("Min Average Client Throughput Excluding Min/Max: clientName=" + clientName + ", value=" + clientVal);
|
||||||
|
xmlFileWriter.println("<prop key='" + KEY_MIN_CLIENT_AVE_EMM_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>");
|
||||||
|
|
||||||
|
val = (String)summary.get(KEY_MAX_CLIENT_AVE_EMM_TP);
|
||||||
|
clientName = val.substring(0, val.indexOf("="));
|
||||||
|
clientVal = val.substring(val.indexOf("=") + 1);
|
||||||
|
System.out.println("Max Average Client Throughput Excluding Min/Max: clientName=" + clientName + ", value=" + clientVal);
|
||||||
|
xmlFileWriter.println("<prop key='" + KEY_MAX_CLIENT_AVE_EMM_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>");
|
||||||
|
|
||||||
|
xmlFileWriter.println("</props>");
|
||||||
|
xmlFileWriter.println("</property>");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void writeMap(String name, Map map) {
|
||||||
|
xmlFileWriter.println("<property name='" + name + "'>");
|
||||||
|
xmlFileWriter.println("<props>");
|
||||||
|
for (Iterator i=map.keySet().iterator(); i.hasNext();) {
|
||||||
|
String propKey = (String)i.next();
|
||||||
|
Object propVal = map.get(propKey);
|
||||||
|
xmlFileWriter.println("<prop key='" + propKey + "'>" + propVal.toString() + "</prop>");
|
||||||
|
}
|
||||||
|
xmlFileWriter.println("</props>");
|
||||||
|
xmlFileWriter.println("</property>");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void parsePerfCsvData(String csvData) {
|
||||||
|
StringTokenizer tokenizer = new StringTokenizer(csvData, ",");
|
||||||
|
String data, key, val, clientName = null;
|
||||||
|
Long throughput = null;
|
||||||
|
int index = -1;
|
||||||
|
while (tokenizer.hasMoreTokens()) {
|
||||||
|
data = tokenizer.nextToken();
|
||||||
|
key = data.substring(0, data.indexOf("="));
|
||||||
|
val = data.substring(data.indexOf("=") + 1);
|
||||||
|
|
||||||
|
if (key.equalsIgnoreCase("clientName")) {
|
||||||
|
clientName = val;
|
||||||
|
} else if (key.equalsIgnoreCase("throughput")) {
|
||||||
|
throughput = Long.valueOf(val);
|
||||||
|
} else if (key.equalsIgnoreCase("index")) {
|
||||||
|
index = Integer.parseInt(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addToClientTPList(clientName, throughput);
|
||||||
|
xmlFileWriter.println("<value index='" + index + "' clientName='" + clientName +
|
||||||
|
"'>" + throughput.longValue() + "</value>");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue