package hudson.plugins.performance; import hudson.Extension; import hudson.model.AbstractBuild; import hudson.model.TaskListener; import hudson.util.IOException2; import org.kohsuke.stapler.DataBoundConstructor; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import java.io.File; 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; /** * 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"; } @Override public Collection<PerformanceReport> parse(AbstractBuild<?, ?> build, Collection<File> reports, TaskListener listener) throws IOException { List<PerformanceReport> result = new ArrayList<PerformanceReport>(); SAXParserFactory factory = SAXParserFactory.newInstance(); factory.setValidating(false); factory.setNamespaceAware(false); PrintStream logger = listener.getLogger(); for (File f : reports) { try { SAXParser parser = factory.newSAXParser(); final PerformanceReport r = new PerformanceReport(); r.setReportFileName(f.getName()); logger.println("Performance: Parsing JMeter report file " + f.getName()); parser.parse(f, new DefaultHandler() { /** * 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")); r.addSample(sample); } } }); result.add(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; } }