/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.StringTokenizer; import org.apache.activemq.tool.reports.plugins.CpuReportPlugin; import org.apache.activemq.tool.reports.plugins.ThroughputReportPlugin; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class XmlFilePerfReportWriter extends AbstractPerfReportWriter { private static final Logger LOG = LoggerFactory.getLogger(XmlFilePerfReportWriter.class); private File tempLogFile; private PrintWriter tempLogFileWriter; private File xmlFile; private PrintWriter xmlFileWriter; private String reportDir; private String reportName; private Map<String, Properties> testPropsMap; private List<Properties> testPropsList; public XmlFilePerfReportWriter() { this("", "PerformanceReport.xml"); } public XmlFilePerfReportWriter(String reportDir, String reportName) { this.testPropsMap = new HashMap<String, Properties>(); this.testPropsList = new ArrayList<Properties>(); 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 File getXmlFile() { return xmlFile; } public void setXmlFile(File xmlFile) { this.xmlFile = xmlFile; } public void writeInfo(String info) { tempLogFileWriter.println("[INFO]" + info); } public void writeCsvData(int csvType, String csvData) { if (csvType == REPORT_PLUGIN_THROUGHPUT) { tempLogFileWriter.println("[TP-DATA]" + csvData); } else if (csvType == REPORT_PLUGIN_CPU) { tempLogFileWriter.println("[CPU-DATA]" + csvData); } } public void writeProperties(String header, Properties props) { testPropsMap.put(header, props); } public void writeProperties(Properties props) { testPropsList.add(props); } protected File createTempLogFile() { File f; 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(); return new File(path + filename); } protected void writeToXml() { try { xmlFile = createXmlFile(); xmlFileWriter = new PrintWriter(new FileOutputStream(xmlFile)); writeXmlHeader(); writeXmlTestSettings(); writeXmlLogFile(); writeXmlPerfSummary(); writeXmlFooter(); xmlFileWriter.close(); LOG.info("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 test settings for (Iterator<String> i = testPropsMap.keySet().iterator(); i.hasNext();) { String key = i.next(); props = testPropsMap.get(key); writeMap(key, props); } int count = 1; for (Iterator<Properties> i = testPropsList.iterator(); i.hasNext();) { props = i.next(); writeMap("settings" + count++, props); } } protected void writeXmlLogFile() throws IOException { // Write throughput data xmlFileWriter.println("<property name='performanceData'>"); xmlFileWriter.println("<list>"); try (FileInputStream fileInputStream = new FileInputStream(tempLogFile); InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream); BufferedReader reader = new BufferedReader(inputStreamReader)) { String line; while ((line = reader.readLine()) != null) { if (line.startsWith("[TP-DATA]")) { handleCsvData(REPORT_PLUGIN_THROUGHPUT, line.substring("[TP-DATA]".length())); parsePerfCsvData("tpdata", line.substring("[TP-DATA]".length())); } else if (line.startsWith("[CPU-DATA]")) { handleCsvData(REPORT_PLUGIN_CPU, line.substring("[CPU-DATA]".length())); parsePerfCsvData("cpudata", line.substring("[CPU-DATA]".length())); } else if (line.startsWith("[INFO]")) { xmlFileWriter.println("<info>" + line + "</info>"); } else { xmlFileWriter.println("<error>" + line + "</error>"); } } } xmlFileWriter.println("</list>"); xmlFileWriter.println("</property>"); } protected void writeXmlPerfSummary() { Map summary; summary = getSummary(REPORT_PLUGIN_THROUGHPUT); if (summary != null && summary.size() > 0) { writeThroughputSummary(summary); } summary = getSummary(REPORT_PLUGIN_CPU); if (summary != null && summary.size() > 0) { writeCpuSummary(summary); } } protected void writeThroughputSummary(Map summary) { // Write throughput summary xmlFileWriter.println("<property name='perfTpSummary'>"); xmlFileWriter.println("<props>"); String val; String clientName; String clientVal; System.out.println("#########################################"); System.out.println("#### SYSTEM THROUGHPUT SUMMARY ####"); System.out.println("#########################################"); val = (String)summary.get(ThroughputReportPlugin.KEY_SYS_TOTAL_TP); System.out.println("System Total Throughput: " + val); xmlFileWriter.println("<prop key='" + ThroughputReportPlugin.KEY_SYS_TOTAL_TP + "'>" + val + "</prop>"); val = (String)summary.get(ThroughputReportPlugin.KEY_SYS_TOTAL_CLIENTS); System.out.println("System Total Clients: " + val); xmlFileWriter.println("<prop key='" + ThroughputReportPlugin.KEY_SYS_TOTAL_CLIENTS + "'>" + val + "</prop>"); val = (String)summary.get(ThroughputReportPlugin.KEY_SYS_AVE_TP); System.out.println("System Average Throughput: " + val); xmlFileWriter.println("<prop key='" + ThroughputReportPlugin.KEY_SYS_AVE_TP + "'>" + val + "</prop>"); val = (String)summary.get(ThroughputReportPlugin.KEY_SYS_AVE_EMM_TP); System.out.println("System Average Throughput Excluding Min/Max: " + val); xmlFileWriter.println("<prop key='" + ThroughputReportPlugin.KEY_SYS_AVE_EMM_TP + "'>" + val + "</prop>"); val = (String)summary.get(ThroughputReportPlugin.KEY_SYS_AVE_CLIENT_TP); System.out.println("System Average Client Throughput: " + val); xmlFileWriter.println("<prop key='" + ThroughputReportPlugin.KEY_SYS_AVE_CLIENT_TP + "'>" + val + "</prop>"); val = (String)summary.get(ThroughputReportPlugin.KEY_SYS_AVE_CLIENT_EMM_TP); System.out.println("System Average Client Throughput Excluding Min/Max: " + val); xmlFileWriter.println("<prop key='" + ThroughputReportPlugin.KEY_SYS_AVE_CLIENT_EMM_TP + "'>" + val + "</prop>"); val = (String)summary.get(ThroughputReportPlugin.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='" + ThroughputReportPlugin.KEY_MIN_CLIENT_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>"); val = (String)summary.get(ThroughputReportPlugin.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='" + ThroughputReportPlugin.KEY_MAX_CLIENT_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>"); val = (String)summary.get(ThroughputReportPlugin.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='" + ThroughputReportPlugin.KEY_MIN_CLIENT_TOTAL_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>"); val = (String)summary.get(ThroughputReportPlugin.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='" + ThroughputReportPlugin.KEY_MAX_CLIENT_TOTAL_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>"); val = (String)summary.get(ThroughputReportPlugin.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='" + ThroughputReportPlugin.KEY_MIN_CLIENT_AVE_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>"); val = (String)summary.get(ThroughputReportPlugin.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='" + ThroughputReportPlugin.KEY_MAX_CLIENT_AVE_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>"); val = (String)summary.get(ThroughputReportPlugin.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='" + ThroughputReportPlugin.KEY_MIN_CLIENT_AVE_EMM_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>"); val = (String)summary.get(ThroughputReportPlugin.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='" + ThroughputReportPlugin.KEY_MAX_CLIENT_AVE_EMM_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>"); xmlFileWriter.println("</props>"); xmlFileWriter.println("</property>"); } protected void writeCpuSummary(Map summary) { xmlFileWriter.println("<property name='perfTpSummary'>"); xmlFileWriter.println("<props>"); System.out.println("########################################"); System.out.println("#### SYSTEM CPU USAGE SUMMARY ####"); System.out.println("########################################"); xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_BLOCK_RECV + "'>" + summary.get(CpuReportPlugin.KEY_BLOCK_RECV) + "</prop>"); System.out.println("Total Blocks Received: " + summary.get(CpuReportPlugin.KEY_BLOCK_RECV)); xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_AVE_BLOCK_RECV + "'>" + summary.get(CpuReportPlugin.KEY_AVE_BLOCK_RECV) + "</prop>"); System.out.println("Ave Blocks Received: " + summary.get(CpuReportPlugin.KEY_AVE_BLOCK_RECV)); xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_BLOCK_SENT + "'>" + summary.get(CpuReportPlugin.KEY_BLOCK_SENT) + "</prop>"); System.out.println("Total Blocks Sent: " + summary.get(CpuReportPlugin.KEY_BLOCK_SENT)); xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_AVE_BLOCK_SENT + "'>" + summary.get(CpuReportPlugin.KEY_AVE_BLOCK_SENT) + "</prop>"); System.out.println("Ave Blocks Sent: " + summary.get(CpuReportPlugin.KEY_AVE_BLOCK_SENT)); xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_CTX_SWITCH + "'>" + summary.get(CpuReportPlugin.KEY_CTX_SWITCH) + "</prop>"); System.out.println("Total Context Switches: " + summary.get(CpuReportPlugin.KEY_CTX_SWITCH)); xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_AVE_CTX_SWITCH + "'>" + summary.get(CpuReportPlugin.KEY_AVE_CTX_SWITCH) + "</prop>"); System.out.println("Ave Context Switches: " + summary.get(CpuReportPlugin.KEY_AVE_CTX_SWITCH)); xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_USER_TIME + "'>" + summary.get(CpuReportPlugin.KEY_USER_TIME) + "</prop>"); System.out.println("Total User Time: " + summary.get(CpuReportPlugin.KEY_USER_TIME)); xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_AVE_USER_TIME + "'>" + summary.get(CpuReportPlugin.KEY_AVE_USER_TIME) + "</prop>"); System.out.println("Ave User Time: " + summary.get(CpuReportPlugin.KEY_AVE_USER_TIME)); xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_SYS_TIME + "'>" + summary.get(CpuReportPlugin.KEY_SYS_TIME) + "</prop>"); System.out.println("Total System Time: " + summary.get(CpuReportPlugin.KEY_SYS_TIME)); xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_AVE_SYS_TIME + "'>" + summary.get(CpuReportPlugin.KEY_AVE_SYS_TIME) + "</prop>"); System.out.println("Ave System Time: " + summary.get(CpuReportPlugin.KEY_AVE_SYS_TIME)); xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_IDLE_TIME + "'>" + summary.get(CpuReportPlugin.KEY_IDLE_TIME) + "</prop>"); System.out.println("Total Idle Time: " + summary.get(CpuReportPlugin.KEY_IDLE_TIME)); xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_AVE_IDLE_TIME + "'>" + summary.get(CpuReportPlugin.KEY_AVE_IDLE_TIME) + "</prop>"); System.out.println("Ave Idle Time: " + summary.get(CpuReportPlugin.KEY_AVE_IDLE_TIME)); xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_WAIT_TIME + "'>" + summary.get(CpuReportPlugin.KEY_WAIT_TIME) + "</prop>"); System.out.println("Total Wait Time: " + summary.get(CpuReportPlugin.KEY_WAIT_TIME)); xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_AVE_WAIT_TIME + "'>" + summary.get(CpuReportPlugin.KEY_AVE_WAIT_TIME) + "</prop>"); System.out.println("Ave Wait Time: " + summary.get(CpuReportPlugin.KEY_AVE_WAIT_TIME)); 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 elementName, String csvData) { StringTokenizer tokenizer = new StringTokenizer(csvData, ",;"); String xmlElement; xmlElement = "<" + elementName; String data; String key; String val; while (tokenizer.hasMoreTokens()) { data = tokenizer.nextToken(); key = data.substring(0, data.indexOf("=")); val = data.substring(data.indexOf("=") + 1); xmlElement += " " + key + "='" + val + "'"; } xmlElement += " />"; xmlFileWriter.println(xmlElement); } }