Skip to content

Commit

Permalink
Updated Locust parser (#199)
Browse files Browse the repository at this point in the history
* Updated Locust parser
Implemented Locust parser framework

* Reworked double to long conversion

* example data from latest locust

---------

Co-authored-by: Alexander Straube <alexander.straube@gmail.com>
  • Loading branch information
bhanteem and a-st authored Oct 4, 2023
1 parent a073d40 commit 71d3163
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 31 deletions.
40 changes: 28 additions & 12 deletions src/main/java/hudson/plugins/performance/parsers/LocustParser.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package hudson.plugins.performance.parsers;

import hudson.Extension;
import hudson.plugins.performance.data.HttpSample;
import hudson.plugins.performance.descriptors.PerformanceReportParserDescriptor;
import hudson.plugins.performance.reports.PerformanceReport;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
Expand All @@ -13,10 +15,11 @@
import java.io.Reader;
import java.util.Date;
import java.util.List;
import org.kohsuke.stapler.DataBoundConstructor;

public class LocustParser extends AbstractParser {
enum ReportColumns {
Method(0), Name(1), Requests(2), Failures(3), Median(4),
Type(0), Name(1), Requests(2), Failures(3), Median(4),
Average(5), Min(6), Max(7), AvgContentSize(8), Rps(9);

int column;
Expand All @@ -30,10 +33,23 @@ int getColumn() {
}
}

public LocustParser(final String glob, final String percentiles, final String filterRegex) {
public LocustParser(String glob, String percentiles) {
super(glob, percentiles, PerformanceReport.INCLUDE_ALL);
}

@DataBoundConstructor
public LocustParser(String glob, String percentiles, String filterRegex) {
super(glob, percentiles, filterRegex);
}

@Extension
public static class DescriptorImpl extends PerformanceReportParserDescriptor {
@Override
public String getDisplayName() {
return "Locust";
}
}

@Override
PerformanceReport parse(final File reportFile) throws Exception {
PerformanceReport report = createPerformanceReport();
Expand All @@ -45,15 +61,15 @@ PerformanceReport parse(final File reportFile) throws Exception {

for (CSVRecord record : reportData) {
String name = record.get(ReportColumns.Name.getColumn());
long average = Long.parseLong(record.get(ReportColumns.Average.getColumn()));
long min = Long.parseLong(record.get(ReportColumns.Min.getColumn()));
long max = Long.parseLong(record.get(ReportColumns.Max.getColumn()));
long failures = Long.parseLong(record.get(ReportColumns.Failures.getColumn()));
long success = Long.parseLong(record.get(ReportColumns.Requests.getColumn()));
float errors = Float.valueOf(failures / success);
long avgContentSize = Long.parseLong(record.get(ReportColumns.AvgContentSize.getColumn()));

if (name.equals("Total")) {
long average = Double.valueOf(record.get(ReportColumns.Average.getColumn())).longValue();
long min = Double.valueOf(record.get(ReportColumns.Min.getColumn())).longValue();
long max = Double.valueOf(record.get(ReportColumns.Max.getColumn())).longValue();
long failures = Double.valueOf(record.get(ReportColumns.Failures.getColumn())).longValue();
long success = Double.valueOf(record.get(ReportColumns.Requests.getColumn())).longValue();
long errors = Double.valueOf(failures / success).longValue();
long avgContentSize = Double.valueOf(record.get(ReportColumns.AvgContentSize.getColumn())).longValue();

if (name.equals("Aggregated")) {
report.setSummarizerSize(reportData.size() - 1);
report.setSummarizerAvg(average);
report.setSummarizerMin(min);
Expand Down Expand Up @@ -93,6 +109,6 @@ List<CSVRecord> getCsvData(final File reportFile) {

@Override
public String getDefaultGlobPattern() {
return "**/*.csv";
return "**/*_stats.csv";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,9 @@ protected static String detectXMLFileType(final InputStream in) throws XMLStream
*/
private static boolean isLocustFileType(String line) {
String[] fileLineHeader = line.replaceAll("\"", "").split(",");
String[] expectedHeaderFields = new String[]{"Method", "Name", "# requests", "# failures",
"Median response time", "Average response time", "Min response time", "Max response time",
String[] expectedHeaderFields = new String[]{"Type", "Name", "Request Count", "Failure Count",
"Median Response Time", "Average Response Time", "Min Response Time", "Max Response Time",
"Average Content Size", "Requests/s"};
return (Arrays.equals(fileLineHeader, expectedHeaderFields));
return (Arrays.asList(fileLineHeader).containsAll(Arrays.asList(expectedHeaderFields)));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class ParserFactory {
defaultGlobPatterns.put("**/*.xml", TaurusParser.class.getSimpleName());
defaultGlobPatterns.put("**/*.wrk", WrkSummarizerParser.class.getSimpleName());
defaultGlobPatterns.put("**/*.mdb", LoadRunnerParser.class.getSimpleName());
defaultGlobPatterns.put("**/*_stats.csv", LocustParser.class.getSimpleName());
}

public static List<PerformanceReportParser> getParser(Run<?, ?> build, FilePath workspace, PrintStream logger, String glob,
Expand Down Expand Up @@ -152,6 +153,8 @@ private static PerformanceReportParser getParser(String parserName, String glob,
return new IagoParser(glob, percentiles, filterRegex);
} else if (parserName.equals(LoadRunnerParser.class.getSimpleName())) {
return new LoadRunnerParser(glob, percentiles, filterRegex);
} else if (parserName.equals(LocustParser.class.getSimpleName())) {
return new LocustParser(glob, percentiles, filterRegex);
} else {
throw new IllegalArgumentException("Unknown parser type: " + parserName);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<li>Taurus reports: "**/*.xml"</li>
<li>JUnit report: "**/TEST-*.xml"</li>
<li>wrk report: "**/*.wrk"</li>
<li>Locust report: "**/*_stats.csv"</li>
</ul>

<p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@
import static org.junit.Assert.*;

public class LocustParserTest {
final static String FILE_NAME = "test_results_requests.csv";
final static String FILE_NAME = "test_results_stats.csv";
File requestReportFile;
LocustParser locustParser;
PerformanceReport report;

@Before
public void setUp() throws Exception {
requestReportFile = new File(getClass().getResource(String.format("/%s", FILE_NAME)).toURI());
locustParser = new LocustParser(null, PerformanceReportTest.DEFAULT_PERCENTILES, PerformanceReport.INCLUDE_ALL);
locustParser = new LocustParser(null, PerformanceReportTest.DEFAULT_PERCENTILES);
report = locustParser.parse(requestReportFile);
}

Expand All @@ -29,7 +29,7 @@ public void shouldCreateParser() throws Exception {

@Test
public void parserShouldReturnGlobPattern() throws Exception {
assertEquals("**/*.csv", locustParser.getDefaultGlobPattern());
assertEquals("**/*_stats.csv", locustParser.getDefaultGlobPattern());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ public void testFlow() throws Exception {

filePath = getClass().getResource("/lr-session.mdb").toURI().getPath();
assertEquals(LoadRunnerParser.class.getSimpleName(), ParserDetector.detect(filePath));

filePath = getClass().getResource("/test_results_stats.csv").toURI().getPath();
assertEquals(LocustParser.class.getSimpleName(), ParserDetector.detect(filePath));
}

@Issue("JENKINS-44317")
Expand All @@ -64,12 +67,6 @@ public void testIssue() throws Exception {
assertEquals(JMeterParser.class.getSimpleName(), ParserDetector.detectXMLFileType(getHugeJMeterInputStream()));
}

@Test
public void testLocustReport() throws Exception {
String filePath = getClass().getResource("/test_results_requests.csv").toURI().getPath();
assertEquals(LocustParser.class.getSimpleName(), ParserDetector.detect(filePath));
}

public static InputStream getHugeJMeterInputStream() {
return new SequenceInputStream(getPrefixInputStream(), getInfiniteSampleInputStream());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ public void testFlow() throws Exception {

filePath = getClass().getResource("/summary.log").toURI().getPath();
assertTrue(ParserFactory.getParser(build, workspace, null, filePath, envVars, PerformanceReportTest.DEFAULT_PERCENTILES, PerformanceReport.INCLUDE_ALL).get(0) instanceof JmeterSummarizerParser);

filePath = getClass().getResource("/test_results_stats.csv").toURI().getPath();
assertTrue(ParserFactory.getParser(build, workspace, null, filePath, envVars, PerformanceReportTest.DEFAULT_PERCENTILES, PerformanceReport.INCLUDE_ALL).get(0) instanceof LocustParser);
}

@Test
Expand All @@ -68,6 +71,7 @@ public void testFlowWithGlob() throws Exception {
assertTrue(ParserFactory.getParser(null, null, null, "**/*.wrk", envVars, PerformanceReportTest.DEFAULT_PERCENTILES, PerformanceReport.INCLUDE_ALL).get(0) instanceof WrkSummarizerParser);
assertTrue(ParserFactory.getParser(null, null, null, "**/*.csv", envVars, PerformanceReportTest.DEFAULT_PERCENTILES, PerformanceReport.INCLUDE_ALL).get(0) instanceof JMeterCsvParser);
assertTrue(ParserFactory.getParser(null, null, null, "**/*.log", envVars, PerformanceReportTest.DEFAULT_PERCENTILES, PerformanceReport.INCLUDE_ALL).get(0) instanceof JmeterSummarizerParser);
assertTrue(ParserFactory.getParser(null, null, null, "**/*_stats.csv", envVars, PerformanceReportTest.DEFAULT_PERCENTILES, PerformanceReport.INCLUDE_ALL).get(0) instanceof LocustParser);
}

@Test
Expand Down
6 changes: 0 additions & 6 deletions src/test/resources/test_results_requests.csv

This file was deleted.

12 changes: 12 additions & 0 deletions src/test/resources/test_results_stats.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Type,Name,Request Count,Failure Count,Median Response Time,Average Response Time,Min Response Time,Max Response Time,Average Content Size,Requests/s,Failures/s,50%,66%,75%,80%,90%,95%,98%,99%,99.9%,99.99%,100%

POST,big,638,10,400.0,370.51828915662696,198.03439999999955,906.8718,1.0,1.07917812740814,1.07917812740814,480,510,530,540,570,580,620,630,630,630,630

POST,huge,72,0,800.0,865.0785481927712,411.80529999999993,1993.6761999999989,1.0,0.12917812740814,4.37917812740814,420,470,510,530,550,570,610,700,700,700,700

POST,medium,6535,0,200.0,221.6907592592591,197.3858000000009,469.2998,1.0,10.913655762892281,4.273655762892281,440,480,500,510,530,560,580,630,630,630,630

POST,small,64219,0,200.0,221.009044155844,196.10569999999944,1009.6347999999989,1.0,107.062611033860563,4.062611033860563,450,490,520,530,540,570,580,590,590,590,590

,Aggregated,71464,10000,200.0,223.833905555556,196.10569999999944,1993.6761999999989,1.4444444444443,119.314623051569123,17.094623051569123,450,500,520,530,550,570,600,620,700,700,700

0 comments on commit 71d3163

Please sign in to comment.