diff --git a/pom.xml b/pom.xml
index bb334f750..a05b1dcde 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.xceptance
xlt
- 8.4.0
+ 8.4.1
jar
XLT
@@ -322,7 +322,7 @@
org.jfree
jfreechart
- 1.5.4
+ 1.5.5
diff --git a/src/main/java/com/xceptance/xlt/report/DataParserThread.java b/src/main/java/com/xceptance/xlt/report/DataParserThread.java
index babbdeb6f..5ff89f1a2 100644
--- a/src/main/java/com/xceptance/xlt/report/DataParserThread.java
+++ b/src/main/java/com/xceptance/xlt/report/DataParserThread.java
@@ -80,21 +80,25 @@ class DataParserThread implements Runnable
*/
private final ReportGeneratorConfiguration config;
+ /**
+ * The request processing rules for this thread. Each parser thread gets its own copy of the rule set. This way,
+ * there is no shared state between threads, hence we can more efficiently cache and process stuff.
+ */
+ private final List requestProcessingRules;
+
/**
* Constructor.
*
+ * @param dispatcher
+ * the dispatcher that coordinates result processing
* @param dataRecordFactory
* the data record factory
* @param fromTime
* the start time
* @param toTime
* the end time
- * @param requestProcessingRules
- * the request processing rules
- * @param dispatcher
- * the dispatcher that coordinates result processing
- * @param removeIndexesFromRequestNames
- * whether to automatically remove any indexes from request names
+ * @param config
+ * the report generator settings
*/
public DataParserThread(final Dispatcher dispatcher, final DataRecordFactory dataRecordFactory, final long fromTime, final long toTime,
final ReportGeneratorConfiguration config)
@@ -104,6 +108,8 @@ public DataParserThread(final Dispatcher dispatcher, final DataRecordFactory dat
this.toTime = toTime;
this.dispatcher = dispatcher;
this.config = config;
+
+ requestProcessingRules = config.getRequestProcessingRules();
}
/**
@@ -112,9 +118,6 @@ public DataParserThread(final Dispatcher dispatcher, final DataRecordFactory dat
@Override
public void run()
{
- // each parser gets its own rules. They are all identical, but don't share state, hence we can more
- // efficiently cache and process
- final List requestProcessingRules = config.getRequestProcessingRules();
final boolean removeIndexes = config.getRemoveIndexesFromRequestNames();
final double SAMPLELIMIT = 1 / ((double) config.dataSampleFactor);
@@ -218,7 +221,8 @@ public void run()
}
catch (final Exception ex)
{
- final String msg = String.format("Failed to parse data record at line %,d in file '%s': %s\nLine is: ", lineNumber, file, ex, lines.get(i).toString());
+ final String msg = String.format("Failed to parse data record at line %,d in file '%s': %s\nLine is: ", lineNumber,
+ file, ex, lines.get(i).toString());
LOG.error(msg, ex);
continue;
@@ -295,16 +299,14 @@ else if (adjustTimerName && (data instanceof RequestData || data instanceof Page
* discarding requests.
*
* @param requestData
- * the request data record
+ * the request data record
* @param requestProcessingRules
- * the rules to apply
+ * the rules to apply
* @param removeIndexesFromRequestNames
- * in case we want to clean the name too
- *
+ * in case we want to clean the name too
* @return the processed request data record, or null
if the data record is to be discarded
*/
- private RequestData postprocess(final RequestData requestData,
- final List requestProcessingRules,
+ private RequestData postprocess(final RequestData requestData, final List requestProcessingRules,
final boolean removeIndexesFromRequestNames)
{
// fix up the name first (Product.1.2 -> Product) if so configured
@@ -356,12 +358,11 @@ else if (state == ReturnState.STOP)
}
}
- // ok, we processed all rules for this dataset, get us the final hashcode for the name, because we need that later
+ // ok, we processed all rules for this dataset, get us the final hashcode for the name, because we need that
+ // later
// here the cache is likely still hot, so this is less expensive
requestData.getName().hashCode();
return requestData;
}
-
-
}
diff --git a/src/main/java/com/xceptance/xlt/report/ReportGeneratorConfiguration.java b/src/main/java/com/xceptance/xlt/report/ReportGeneratorConfiguration.java
index 9201f5994..6053ed03d 100644
--- a/src/main/java/com/xceptance/xlt/report/ReportGeneratorConfiguration.java
+++ b/src/main/java/com/xceptance/xlt/report/ReportGeneratorConfiguration.java
@@ -39,7 +39,6 @@
import com.xceptance.xlt.api.report.ReportProvider;
import com.xceptance.xlt.api.report.ReportProviderConfiguration;
import com.xceptance.xlt.api.util.XltException;
-import com.xceptance.xlt.api.util.XltLogger;
import com.xceptance.xlt.api.util.XltProperties;
import com.xceptance.xlt.common.XltConstants;
import com.xceptance.xlt.common.XltPropertyNames;
@@ -79,14 +78,14 @@ public static class ChartCappingInfo
*/
public enum ChartCappingMethod
{
- /** No capping (default). */
- NONE,
+ /** No capping (default). */
+ NONE,
- /** Cap at an absolute value. */
- ABSOLUTE,
+ /** Cap at an absolute value. */
+ ABSOLUTE,
- /** Cap at the n-fold of the average value. */
- NFOLD_OF_AVERAGE
+ /** Cap at the n-fold of the average value. */
+ NFOLD_OF_AVERAGE
};
/**
@@ -94,11 +93,11 @@ public enum ChartCappingMethod
*/
public enum ChartCappingMode
{
- /** Cap the chart at the capping value only if necessary. */
- SMART,
+ /** Cap the chart at the capping value only if necessary. */
+ SMART,
- /** Always cap the chart at the capping value even if the maximum values are below the capping value. */
- ALWAYS
+ /** Always cap the chart at the capping value even if the maximum values are below the capping value. */
+ ALWAYS
};
/**
@@ -163,9 +162,13 @@ public enum ChartCappingMode
// Special settings for profiling and debugging
private static final String PROP_PARSER_THREAD_COUNT = PROP_PREFIX + "parser.threads";
+
private static final String PROP_READER_THREAD_COUNT = PROP_PREFIX + "reader.threads";
+
private static final String PROP_THREAD_QUEUE_SIZE = PROP_PREFIX + "queue.bucketsize";
+
private static final String PROP_THREAD_QUEUE_LENGTH = PROP_PREFIX + "queue.length";
+
private static final String PROP_DATA_SAMPLE_FACTOR = PROP_PREFIX + "data.sampleFactor";
private static final String PROP_TRANSFORMATIONS_PREFIX = PROP_PREFIX + "transformations.";
@@ -243,8 +246,11 @@ public enum ChartCappingMode
private boolean noAgentCharts;
public final int readerThreadCount;
+
public final int parserThreadCount;
+
public final int threadQueueBucketSize;
+
public final int threadQueueLength;
public final int dataSampleFactor;
@@ -276,11 +282,11 @@ public enum ChartCappingMode
private final int transactionErrorOverviewChartLimit;
private final int errorDetailsChartLimit;
-
+
private final int directoryLimitPerError;
-
+
private final double directoryReplacementChance;
-
+
private final int stackTracesLimit;
private final Map apdexThresholdsByActionNamePattern = new HashMap<>();
@@ -408,9 +414,9 @@ public ReportGeneratorConfiguration(Properties xltProperties, final File overrid
directoryLimitPerError = getIntProperty(XltPropertyNames.ReportGenerator.Errors.DIRECTORY_LIMIT_PER_ERROR, 10);
directoryReplacementChance = getDoubleProperty(XltPropertyNames.ReportGenerator.Errors.DIRECTORY_REPLACEMENT_CHANCE, 0.1);
-
+
stackTracesLimit = getIntProperty(XltPropertyNames.ReportGenerator.Errors.STACKTRACES_LIMIT, 500);
-
+
// event settings
groupEventsByTestCase = getBooleanProperty(PROP_PREFIX + "events.groupByTestCase", true);
eventLimit = getIntProperty(PROP_PREFIX + "events.eventLimit", 100);
@@ -483,7 +489,7 @@ private void checkForLeadingZeros(final String s)
}
sb.append("\n");
- throw new RuntimeException(sb.toString());
+ throw new XltException(sb.toString());
}
}
@@ -791,7 +797,7 @@ public int getErrorDetailsChartLimit()
{
return errorDetailsChartLimit;
}
-
+
/**
* The maximum number of directory hints remembered for a certain error (stack trace).
*
@@ -801,9 +807,10 @@ public int getDirectoryLimitPerError()
{
return directoryLimitPerError;
}
-
+
/**
- * The chance to replace directory hints remembered for a certain error (stack trace) when the maximum number is reached.
+ * The chance to replace directory hints remembered for a certain error (stack trace) when the maximum number is
+ * reached.
*
* @return the chance to replace listed directory hints
*/
@@ -811,7 +818,7 @@ public double getDirectoryReplacementChance()
{
return directoryReplacementChance;
}
-
+
/**
* The maximum number of errors that will be saved complete with their stack trace.
*
@@ -1001,7 +1008,6 @@ public int getEventLimitPerTestCase()
return eventLimit;
}
-
/**
* Indicates whether or not to group events by test case.
*
@@ -1012,7 +1018,6 @@ public int getEventMessageLimitPerEvent()
return eventMessageLimit;
}
-
/**
* Returns whether to automatically remove any indexes from the request name (i.e. "HomePage.1.27" -> "HomePage").
*
@@ -1491,15 +1496,15 @@ public List getRequestProcessingRules()
// ensure that either newName or dropOnMatch is set
if (StringUtils.isNotBlank(newName) == dropOnMatch)
{
- throw new RuntimeException(String.format("Either specify property '%s' or set property '%s' to true",
- basePropertyName + ".newName", basePropertyName + ".dropOnMatch"));
+ throw new XltException(String.format("Either specify property '%s' or set property '%s' to true",
+ basePropertyName + ".newName", basePropertyName + ".dropOnMatch"));
}
// ensure that dropOnMatch and stopOnMatch are not contradicting
if (dropOnMatch && !stopOnMatch)
{
- throw new RuntimeException(String.format("If property '%s' is true, property '%s' cannot be false",
- basePropertyName + ".dropOnMatch", basePropertyName + ".stopOnMatch"));
+ throw new XltException(String.format("If property '%s' is true, property '%s' cannot be false",
+ basePropertyName + ".dropOnMatch", basePropertyName + ".stopOnMatch"));
}
// create and validate the rules
@@ -1518,7 +1523,6 @@ public List getRequestProcessingRules()
{
// Log it and continue with next rule.
final String errMsg = "Request processing rule '" + basePropertyName + "' is invalid. " + imre.getMessage();
- XltLogger.reportLogger.error(errMsg, imre);
System.err.println(errMsg);
// remember that we encountered an invalid merge rule
invalidRulePresent = true;
@@ -1527,7 +1531,7 @@ public List getRequestProcessingRules()
if (invalidRulePresent)
{
- throw new RuntimeException("Please check your configuration. At least one request processing rule is invalid and needs to be fixed.");
+ throw new XltException("Please check your configuration. At least one request processing rule is invalid and needs to be fixed.");
}
return requestProcessingRules;