001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.activemq.tool.reports; 018 019 import java.io.BufferedOutputStream; 020 import java.io.BufferedReader; 021 import java.io.File; 022 import java.io.FileInputStream; 023 import java.io.FileNotFoundException; 024 import java.io.FileOutputStream; 025 import java.io.IOException; 026 import java.io.InputStreamReader; 027 import java.io.PrintWriter; 028 import java.util.ArrayList; 029 import java.util.HashMap; 030 import java.util.Iterator; 031 import java.util.List; 032 import java.util.Map; 033 import java.util.Properties; 034 import java.util.StringTokenizer; 035 036 import org.apache.activemq.tool.reports.plugins.CpuReportPlugin; 037 import org.apache.activemq.tool.reports.plugins.ThroughputReportPlugin; 038 import org.apache.commons.logging.Log; 039 import org.apache.commons.logging.LogFactory; 040 041 public class XmlFilePerfReportWriter extends AbstractPerfReportWriter { 042 043 private static final Log LOG = LogFactory.getLog(XmlFilePerfReportWriter.class); 044 045 private File tempLogFile; 046 private PrintWriter tempLogFileWriter; 047 048 private File xmlFile; 049 private PrintWriter xmlFileWriter; 050 051 private String reportDir; 052 private String reportName; 053 054 private Map<String, Properties> testPropsMap; 055 private List<Properties> testPropsList; 056 057 public XmlFilePerfReportWriter() { 058 this("", "PerformanceReport.xml"); 059 } 060 061 public XmlFilePerfReportWriter(String reportDir, String reportName) { 062 this.testPropsMap = new HashMap<String, Properties>(); 063 this.testPropsList = new ArrayList<Properties>(); 064 this.reportDir = reportDir; 065 this.reportName = reportName; 066 } 067 068 public void openReportWriter() { 069 if (tempLogFile == null) { 070 tempLogFile = createTempLogFile(); 071 } 072 073 try { 074 // Disable auto-flush and allocate 100kb of buffer 075 tempLogFileWriter = new PrintWriter(new BufferedOutputStream(new FileOutputStream(tempLogFile), 102400), false); 076 } catch (FileNotFoundException e) { 077 e.printStackTrace(); 078 } 079 } 080 081 public void closeReportWriter() { 082 // Flush and close log file writer 083 tempLogFileWriter.flush(); 084 tempLogFileWriter.close(); 085 086 writeToXml(); 087 } 088 089 public String getReportDir() { 090 return reportDir; 091 } 092 093 public void setReportDir(String reportDir) { 094 this.reportDir = reportDir; 095 } 096 097 public String getReportName() { 098 return reportName; 099 } 100 101 public void setReportName(String reportName) { 102 this.reportName = reportName; 103 } 104 105 public File getXmlFile() { 106 return xmlFile; 107 } 108 109 public void setXmlFile(File xmlFile) { 110 this.xmlFile = xmlFile; 111 } 112 113 public void writeInfo(String info) { 114 tempLogFileWriter.println("[INFO]" + info); 115 } 116 117 public void writeCsvData(int csvType, String csvData) { 118 if (csvType == REPORT_PLUGIN_THROUGHPUT) { 119 tempLogFileWriter.println("[TP-DATA]" + csvData); 120 } else if (csvType == REPORT_PLUGIN_CPU) { 121 tempLogFileWriter.println("[CPU-DATA]" + csvData); 122 } 123 } 124 125 public void writeProperties(String header, Properties props) { 126 testPropsMap.put(header, props); 127 } 128 129 public void writeProperties(Properties props) { 130 testPropsList.add(props); 131 } 132 133 protected File createTempLogFile() { 134 File f; 135 try { 136 f = File.createTempFile("tmpPL", null); 137 } catch (IOException e) { 138 f = new File("tmpPL" + System.currentTimeMillis() + ".tmp"); 139 } 140 f.deleteOnExit(); 141 return f; 142 } 143 144 protected File createXmlFile() { 145 String filename = getReportName().endsWith(".xml") ? getReportName() : (getReportName() + ".xml"); 146 String path = (getReportDir() == null) ? "" : getReportDir(); 147 148 return new File(path + filename); 149 } 150 151 protected void writeToXml() { 152 try { 153 xmlFile = createXmlFile(); 154 xmlFileWriter = new PrintWriter(new FileOutputStream(xmlFile)); 155 writeXmlHeader(); 156 writeXmlTestSettings(); 157 writeXmlLogFile(); 158 writeXmlPerfSummary(); 159 writeXmlFooter(); 160 xmlFileWriter.close(); 161 162 LOG.info("Created performance report: " + xmlFile.getAbsolutePath()); 163 } catch (Exception e) { 164 e.printStackTrace(); 165 } 166 } 167 168 protected void writeXmlHeader() { 169 xmlFileWriter.println("<testResult>"); 170 } 171 172 protected void writeXmlFooter() { 173 xmlFileWriter.println("</testResult>"); 174 } 175 176 protected void writeXmlTestSettings() { 177 Properties props; 178 179 // Write test settings 180 for (Iterator<String> i = testPropsMap.keySet().iterator(); i.hasNext();) { 181 String key = i.next(); 182 props = testPropsMap.get(key); 183 writeMap(key, props); 184 } 185 186 int count = 1; 187 for (Iterator<Properties> i = testPropsList.iterator(); i.hasNext();) { 188 props = i.next(); 189 writeMap("settings" + count++, props); 190 } 191 } 192 193 protected void writeXmlLogFile() throws IOException { 194 // Write throughput data 195 xmlFileWriter.println("<property name='performanceData'>"); 196 xmlFileWriter.println("<list>"); 197 198 BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(tempLogFile))); 199 String line; 200 while ((line = reader.readLine()) != null) { 201 if (line.startsWith("[TP-DATA]")) { 202 handleCsvData(REPORT_PLUGIN_THROUGHPUT, line.substring("[TP-DATA]".length())); 203 parsePerfCsvData("tpdata", line.substring("[TP-DATA]".length())); 204 } else if (line.startsWith("[CPU-DATA]")) { 205 handleCsvData(REPORT_PLUGIN_CPU, line.substring("[CPU-DATA]".length())); 206 parsePerfCsvData("cpudata", line.substring("[CPU-DATA]".length())); 207 } else if (line.startsWith("[INFO]")) { 208 xmlFileWriter.println("<info>" + line + "</info>"); 209 } else { 210 xmlFileWriter.println("<error>" + line + "</error>"); 211 } 212 } 213 214 xmlFileWriter.println("</list>"); 215 xmlFileWriter.println("</property>"); 216 } 217 218 protected void writeXmlPerfSummary() { 219 220 Map summary; 221 222 summary = getSummary(REPORT_PLUGIN_THROUGHPUT); 223 if (summary != null && summary.size() > 0) { 224 writeThroughputSummary(summary); 225 } 226 227 summary = getSummary(REPORT_PLUGIN_CPU); 228 if (summary != null && summary.size() > 0) { 229 writeCpuSummary(summary); 230 } 231 232 } 233 234 protected void writeThroughputSummary(Map summary) { 235 // Write throughput summary 236 xmlFileWriter.println("<property name='perfTpSummary'>"); 237 xmlFileWriter.println("<props>"); 238 239 String val; 240 String clientName; 241 String clientVal; 242 243 System.out.println("#########################################"); 244 System.out.println("#### SYSTEM THROUGHPUT SUMMARY ####"); 245 System.out.println("#########################################"); 246 247 val = (String)summary.get(ThroughputReportPlugin.KEY_SYS_TOTAL_TP); 248 System.out.println("System Total Throughput: " + val); 249 xmlFileWriter.println("<prop key='" + ThroughputReportPlugin.KEY_SYS_TOTAL_TP + "'>" + val + "</prop>"); 250 251 val = (String)summary.get(ThroughputReportPlugin.KEY_SYS_TOTAL_CLIENTS); 252 System.out.println("System Total Clients: " + val); 253 xmlFileWriter.println("<prop key='" + ThroughputReportPlugin.KEY_SYS_TOTAL_CLIENTS + "'>" + val + "</prop>"); 254 255 val = (String)summary.get(ThroughputReportPlugin.KEY_SYS_AVE_TP); 256 System.out.println("System Average Throughput: " + val); 257 xmlFileWriter.println("<prop key='" + ThroughputReportPlugin.KEY_SYS_AVE_TP + "'>" + val + "</prop>"); 258 259 val = (String)summary.get(ThroughputReportPlugin.KEY_SYS_AVE_EMM_TP); 260 System.out.println("System Average Throughput Excluding Min/Max: " + val); 261 xmlFileWriter.println("<prop key='" + ThroughputReportPlugin.KEY_SYS_AVE_EMM_TP + "'>" + val + "</prop>"); 262 263 val = (String)summary.get(ThroughputReportPlugin.KEY_SYS_AVE_CLIENT_TP); 264 System.out.println("System Average Client Throughput: " + val); 265 xmlFileWriter.println("<prop key='" + ThroughputReportPlugin.KEY_SYS_AVE_CLIENT_TP + "'>" + val + "</prop>"); 266 267 val = (String)summary.get(ThroughputReportPlugin.KEY_SYS_AVE_CLIENT_EMM_TP); 268 System.out.println("System Average Client Throughput Excluding Min/Max: " + val); 269 xmlFileWriter.println("<prop key='" + ThroughputReportPlugin.KEY_SYS_AVE_CLIENT_EMM_TP + "'>" + val + "</prop>"); 270 271 val = (String)summary.get(ThroughputReportPlugin.KEY_MIN_CLIENT_TP); 272 clientName = val.substring(0, val.indexOf("=")); 273 clientVal = val.substring(val.indexOf("=") + 1); 274 System.out.println("Min Client Throughput Per Sample: clientName=" + clientName + ", value=" + clientVal); 275 xmlFileWriter.println("<prop key='" + ThroughputReportPlugin.KEY_MIN_CLIENT_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>"); 276 277 val = (String)summary.get(ThroughputReportPlugin.KEY_MAX_CLIENT_TP); 278 clientName = val.substring(0, val.indexOf("=")); 279 clientVal = val.substring(val.indexOf("=") + 1); 280 System.out.println("Max Client Throughput Per Sample: clientName=" + clientName + ", value=" + clientVal); 281 xmlFileWriter.println("<prop key='" + ThroughputReportPlugin.KEY_MAX_CLIENT_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>"); 282 283 val = (String)summary.get(ThroughputReportPlugin.KEY_MIN_CLIENT_TOTAL_TP); 284 clientName = val.substring(0, val.indexOf("=")); 285 clientVal = val.substring(val.indexOf("=") + 1); 286 System.out.println("Min Client Total Throughput: clientName=" + clientName + ", value=" + clientVal); 287 xmlFileWriter.println("<prop key='" + ThroughputReportPlugin.KEY_MIN_CLIENT_TOTAL_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>"); 288 289 val = (String)summary.get(ThroughputReportPlugin.KEY_MAX_CLIENT_TOTAL_TP); 290 clientName = val.substring(0, val.indexOf("=")); 291 clientVal = val.substring(val.indexOf("=") + 1); 292 System.out.println("Max Client Total Throughput: clientName=" + clientName + ", value=" + clientVal); 293 xmlFileWriter.println("<prop key='" + ThroughputReportPlugin.KEY_MAX_CLIENT_TOTAL_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>"); 294 295 val = (String)summary.get(ThroughputReportPlugin.KEY_MIN_CLIENT_AVE_TP); 296 clientName = val.substring(0, val.indexOf("=")); 297 clientVal = val.substring(val.indexOf("=") + 1); 298 System.out.println("Min Average Client Throughput: clientName=" + clientName + ", value=" + clientVal); 299 xmlFileWriter.println("<prop key='" + ThroughputReportPlugin.KEY_MIN_CLIENT_AVE_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>"); 300 301 val = (String)summary.get(ThroughputReportPlugin.KEY_MAX_CLIENT_AVE_TP); 302 clientName = val.substring(0, val.indexOf("=")); 303 clientVal = val.substring(val.indexOf("=") + 1); 304 System.out.println("Max Average Client Throughput: clientName=" + clientName + ", value=" + clientVal); 305 xmlFileWriter.println("<prop key='" + ThroughputReportPlugin.KEY_MAX_CLIENT_AVE_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>"); 306 307 val = (String)summary.get(ThroughputReportPlugin.KEY_MIN_CLIENT_AVE_EMM_TP); 308 clientName = val.substring(0, val.indexOf("=")); 309 clientVal = val.substring(val.indexOf("=") + 1); 310 System.out.println("Min Average Client Throughput Excluding Min/Max: clientName=" + clientName + ", value=" + clientVal); 311 xmlFileWriter.println("<prop key='" + ThroughputReportPlugin.KEY_MIN_CLIENT_AVE_EMM_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>"); 312 313 val = (String)summary.get(ThroughputReportPlugin.KEY_MAX_CLIENT_AVE_EMM_TP); 314 clientName = val.substring(0, val.indexOf("=")); 315 clientVal = val.substring(val.indexOf("=") + 1); 316 System.out.println("Max Average Client Throughput Excluding Min/Max: clientName=" + clientName + ", value=" + clientVal); 317 xmlFileWriter.println("<prop key='" + ThroughputReportPlugin.KEY_MAX_CLIENT_AVE_EMM_TP + "'>clientName=" + clientName + ",value=" + clientVal + "</prop>"); 318 319 xmlFileWriter.println("</props>"); 320 xmlFileWriter.println("</property>"); 321 } 322 323 protected void writeCpuSummary(Map summary) { 324 xmlFileWriter.println("<property name='perfTpSummary'>"); 325 xmlFileWriter.println("<props>"); 326 327 System.out.println("########################################"); 328 System.out.println("#### SYSTEM CPU USAGE SUMMARY ####"); 329 System.out.println("########################################"); 330 331 xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_BLOCK_RECV + "'>" + summary.get(CpuReportPlugin.KEY_BLOCK_RECV) + "</prop>"); 332 System.out.println("Total Blocks Received: " + summary.get(CpuReportPlugin.KEY_BLOCK_RECV)); 333 334 xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_AVE_BLOCK_RECV + "'>" + summary.get(CpuReportPlugin.KEY_AVE_BLOCK_RECV) + "</prop>"); 335 System.out.println("Ave Blocks Received: " + summary.get(CpuReportPlugin.KEY_AVE_BLOCK_RECV)); 336 337 xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_BLOCK_SENT + "'>" + summary.get(CpuReportPlugin.KEY_BLOCK_SENT) + "</prop>"); 338 System.out.println("Total Blocks Sent: " + summary.get(CpuReportPlugin.KEY_BLOCK_SENT)); 339 340 xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_AVE_BLOCK_SENT + "'>" + summary.get(CpuReportPlugin.KEY_AVE_BLOCK_SENT) + "</prop>"); 341 System.out.println("Ave Blocks Sent: " + summary.get(CpuReportPlugin.KEY_AVE_BLOCK_SENT)); 342 343 xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_CTX_SWITCH + "'>" + summary.get(CpuReportPlugin.KEY_CTX_SWITCH) + "</prop>"); 344 System.out.println("Total Context Switches: " + summary.get(CpuReportPlugin.KEY_CTX_SWITCH)); 345 346 xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_AVE_CTX_SWITCH + "'>" + summary.get(CpuReportPlugin.KEY_AVE_CTX_SWITCH) + "</prop>"); 347 System.out.println("Ave Context Switches: " + summary.get(CpuReportPlugin.KEY_AVE_CTX_SWITCH)); 348 349 xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_USER_TIME + "'>" + summary.get(CpuReportPlugin.KEY_USER_TIME) + "</prop>"); 350 System.out.println("Total User Time: " + summary.get(CpuReportPlugin.KEY_USER_TIME)); 351 352 xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_AVE_USER_TIME + "'>" + summary.get(CpuReportPlugin.KEY_AVE_USER_TIME) + "</prop>"); 353 System.out.println("Ave User Time: " + summary.get(CpuReportPlugin.KEY_AVE_USER_TIME)); 354 355 xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_SYS_TIME + "'>" + summary.get(CpuReportPlugin.KEY_SYS_TIME) + "</prop>"); 356 System.out.println("Total System Time: " + summary.get(CpuReportPlugin.KEY_SYS_TIME)); 357 358 xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_AVE_SYS_TIME + "'>" + summary.get(CpuReportPlugin.KEY_AVE_SYS_TIME) + "</prop>"); 359 System.out.println("Ave System Time: " + summary.get(CpuReportPlugin.KEY_AVE_SYS_TIME)); 360 361 xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_IDLE_TIME + "'>" + summary.get(CpuReportPlugin.KEY_IDLE_TIME) + "</prop>"); 362 System.out.println("Total Idle Time: " + summary.get(CpuReportPlugin.KEY_IDLE_TIME)); 363 364 xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_AVE_IDLE_TIME + "'>" + summary.get(CpuReportPlugin.KEY_AVE_IDLE_TIME) + "</prop>"); 365 System.out.println("Ave Idle Time: " + summary.get(CpuReportPlugin.KEY_AVE_IDLE_TIME)); 366 367 xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_WAIT_TIME + "'>" + summary.get(CpuReportPlugin.KEY_WAIT_TIME) + "</prop>"); 368 System.out.println("Total Wait Time: " + summary.get(CpuReportPlugin.KEY_WAIT_TIME)); 369 370 xmlFileWriter.println("<prop key='" + CpuReportPlugin.KEY_AVE_WAIT_TIME + "'>" + summary.get(CpuReportPlugin.KEY_AVE_WAIT_TIME) + "</prop>"); 371 System.out.println("Ave Wait Time: " + summary.get(CpuReportPlugin.KEY_AVE_WAIT_TIME)); 372 373 xmlFileWriter.println("</props>"); 374 xmlFileWriter.println("</property>"); 375 } 376 377 protected void writeMap(String name, Map map) { 378 xmlFileWriter.println("<property name='" + name + "'>"); 379 xmlFileWriter.println("<props>"); 380 for (Iterator i = map.keySet().iterator(); i.hasNext();) { 381 String propKey = (String)i.next(); 382 Object propVal = map.get(propKey); 383 xmlFileWriter.println("<prop key='" + propKey + "'>" + propVal.toString() + "</prop>"); 384 } 385 xmlFileWriter.println("</props>"); 386 xmlFileWriter.println("</property>"); 387 } 388 389 protected void parsePerfCsvData(String elementName, String csvData) { 390 StringTokenizer tokenizer = new StringTokenizer(csvData, ",;"); 391 String xmlElement; 392 393 xmlElement = "<" + elementName; 394 String data; 395 String key; 396 String val; 397 while (tokenizer.hasMoreTokens()) { 398 data = tokenizer.nextToken(); 399 key = data.substring(0, data.indexOf("=")); 400 val = data.substring(data.indexOf("=") + 1); 401 xmlElement += " " + key + "='" + val + "'"; 402 } 403 xmlElement += " />"; 404 xmlFileWriter.println(xmlElement); 405 } 406 }