package hudson.plugins.performance; import hudson.Extension; import hudson.model.TaskListener; import hudson.model.AbstractBuild; import hudson.util.IOException2; import java.beans.XMLDecoder; import java.beans.XMLEncoder; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.kohsuke.stapler.DataBoundConstructor; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** * Parser for JMeter. * * @author Kohsuke Kawaguchi */ public class JMeterParser extends PerformanceReportParser { @Extension public static class DescriptorImpl extends PerformanceReportParserDescriptor { @Override public String getDisplayName() { return "JMeter"; } } @DataBoundConstructor public JMeterParser(String glob) { super(glob); } @Override public String getDefaultGlobPattern() { return "**/*.jtl"; } private PerformanceReport getPerfCache(File f) { PerformanceReport pr = null; File cf = new File(f.getName() + ".prep"); System.out.println("getPerfCache ->" + cf.getName()); if (cf.canRead()) { XMLDecoder decoder; try { decoder = new XMLDecoder(new FileInputStream(cf.getName())); } catch (FileNotFoundException e) { return (null); } try { pr = (PerformanceReport)decoder.readObject(); } finally { decoder.close(); } } return (pr); } private void savePerfCache(File f, PerformanceReport r ) { File cf = new File(f.getName() + ".prep"); XMLEncoder encoder = null; System.out.println("savePerfCache ->" + cf.getName()); try { encoder = new XMLEncoder(new FileOutputStream(cf.getName())); encoder.writeObject(r); encoder.flush(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if (encoder != null) encoder.close(); } } @Override public Collection parse(AbstractBuild build, Collection reports, TaskListener listener) throws IOException { List result = new ArrayList(); SAXParserFactory factory = SAXParserFactory.newInstance(); factory.setValidating(false); factory.setNamespaceAware(false); PrintStream logger = listener.getLogger(); for (File f : reports) { try { PerformanceReport rc = getPerfCache(f); if (rc != null) result.add(rc); else { final PerformanceReport r = new PerformanceReport(); SAXParser parser = factory.newSAXParser(); r.setReportFileName(f.getName()); logger.println("Performance: Parsing JMeter report file " + f.getName()); parser.parse(f, new DefaultHandler() { HttpSample currentSample; int counter = 0; /** * Performance XML log format is in * http://jakarta.apache.org * /jmeter/usermanual/listeners.html * * There are two different tags which delimit jmeter * samples: httpSample for http samples sample for non http * samples * * There are also two different XML formats which we have to * handle: v2.0 = "label", "timeStamp", "time", "success" * v2.1 = "lb", "ts", "t", "s" * */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if ("httpSample".equalsIgnoreCase(qName) || "sample".equalsIgnoreCase(qName)) { HttpSample sample = new HttpSample(); sample.setDate(new Date( Long.valueOf(attributes.getValue("ts") != null ? attributes.getValue("ts") : attributes.getValue("timeStamp")))); sample.setDuration(Long.valueOf(attributes.getValue("t") != null ? attributes.getValue("t") : attributes.getValue("time"))); sample.setSuccessful(Boolean.valueOf(attributes.getValue("s") != null ? attributes.getValue("s") : attributes.getValue("success"))); sample.setUri(attributes.getValue("lb") != null ? attributes.getValue("lb") : attributes.getValue("label")); if (counter == 0) { currentSample = sample; } counter++; } } @Override public void endElement(String uri, String localName, String qName) { if ("httpSample".equalsIgnoreCase(qName) || "sample".equalsIgnoreCase(qName)) { if (counter == 1) { try { r.addSample(currentSample); } catch (SAXException e) { e.printStackTrace(); } } counter--; } } }); result.add(r); savePerfCache(f, r); } } catch (ParserConfigurationException e) { throw new IOException2("Failed to create parser ", e); } catch (SAXException e) { logger.println("Performance: Failed to parse " + f + ": " + e.getMessage()); } } return result; } }