use of org.apache.jmeter.report.config.GraphConfiguration in project jmeter by apache.
the class ReportGenerator method generate.
/**
* Generate dashboard reports using the data from the specified CSV File.
*
* @throws GenerationException when the generation failed
*/
public void generate() throws GenerationException {
if (resultCollector != null) {
log.info("Flushing result collector before report Generation");
resultCollector.flushFile();
}
log.debug("Start report generation");
File tmpDir = configuration.getTempDirectory();
boolean tmpDirCreated = createTempDir(tmpDir);
// Build consumers chain
SampleContext sampleContext = new SampleContext();
sampleContext.setWorkingDirectory(tmpDir);
SampleSource source = new CsvFileSampleSource(testFile, CSV_DEFAULT_SEPARATOR);
source.setSampleContext(sampleContext);
NormalizerSampleConsumer normalizer = new NormalizerSampleConsumer();
normalizer.setName(NORMALIZER_CONSUMER_NAME);
FilterConsumer dateRangeConsumer = createFilterByDateRange();
dateRangeConsumer.addSampleConsumer(createBeginDateConsumer());
dateRangeConsumer.addSampleConsumer(createEndDateConsumer());
FilterConsumer nameFilter = createNameFilter();
FilterConsumer excludeControllerFilter = createExcludeControllerFilter();
nameFilter.addSampleConsumer(excludeControllerFilter);
dateRangeConsumer.addSampleConsumer(nameFilter);
normalizer.addSampleConsumer(dateRangeConsumer);
source.addSampleConsumer(normalizer);
// Get graph configurations
Map<String, GraphConfiguration> graphConfigurations = configuration.getGraphConfigurations();
// Process configuration to build graph consumers
for (Map.Entry<String, GraphConfiguration> entryGraphCfg : graphConfigurations.entrySet()) {
addGraphConsumer(nameFilter, excludeControllerFilter, entryGraphCfg);
}
// Generate data
log.debug("Start samples processing");
try {
// NOSONAR
source.run();
} catch (SampleException ex) {
throw new GenerationException("Error while processing samples: " + ex.getMessage(), ex);
}
log.debug("End of samples processing");
log.debug("Start data exporting");
// Process configuration to build data exporters
String key;
ExporterConfiguration value;
for (Map.Entry<String, ExporterConfiguration> entry : configuration.getExportConfigurations().entrySet()) {
key = entry.getKey();
value = entry.getValue();
if (log.isInfoEnabled()) {
log.info("Exporting data using exporter:'{}' of className:'{}'", key, value.getClassName());
}
exportData(sampleContext, key, value);
}
log.debug("End of data exporting");
removeTempDir(tmpDir, tmpDirCreated);
log.debug("End of report generation");
}
use of org.apache.jmeter.report.config.GraphConfiguration in project jmeter by apache.
the class HtmlTemplateExporter method export.
/**
* @see DataExporter#export(SampleContext, File, ReportGeneratorConfiguration)
*/
@Override
public void export(SampleContext context, File file, ReportGeneratorConfiguration configuration) throws ExportException {
Validate.notNull(context, MUST_NOT_BE_NULL, "context");
Validate.notNull(file, MUST_NOT_BE_NULL, "file");
Validate.notNull(configuration, MUST_NOT_BE_NULL, "configuration");
log.debug("Start template processing");
// Create data context and populate it
DataContext dataContext = new DataContext();
// Get the configuration of the current exporter
final ExporterConfiguration exportCfg = configuration.getExportConfigurations().get(getName());
// Get template directory property value
File templateDirectory = getPropertyFromConfig(exportCfg, TEMPLATE_DIR, new File(JMeterUtils.getJMeterBinDir(), TEMPLATE_DIR_NAME_DEFAULT), File.class);
if (!templateDirectory.isDirectory()) {
String message = String.format("\"%s\" is not a valid template directory", templateDirectory.getAbsolutePath());
log.error(message);
throw new ExportException(message);
}
// Get output directory property value
File outputDir = getPropertyFromConfig(exportCfg, OUTPUT_DIR, new File(JMeterUtils.getJMeterBinDir(), OUTPUT_DIR_NAME_DEFAULT), File.class);
String globallyDefinedOutputDir = JMeterUtils.getProperty(JMeter.JMETER_REPORT_OUTPUT_DIR_PROPERTY);
if (!StringUtils.isEmpty(globallyDefinedOutputDir)) {
outputDir = new File(globallyDefinedOutputDir);
}
JOrphanUtils.canSafelyWriteToFolder(outputDir, this::htmlReportFileFilter);
if (log.isInfoEnabled()) {
log.info("Will generate dashboard in folder: {}", outputDir.getAbsolutePath());
}
// Add a flag defining if only sample series are filtered to the context
final boolean filtersOnlySampleSeries = exportCfg.filtersOnlySampleSeries();
addToContext(DATA_CTX_FILTERS_ONLY_SAMPLE_SERIES, filtersOnlySampleSeries, dataContext);
// Add the series filter to the context
final String seriesFilter = exportCfg.getSeriesFilter();
Pattern filterPattern = null;
if (StringUtils.isNotBlank(seriesFilter)) {
try {
filterPattern = Pattern.compile(seriesFilter);
} catch (PatternSyntaxException ex) {
log.error("Invalid series filter: '{}', {}", seriesFilter, ex.getDescription());
}
}
addToContext(DATA_CTX_SERIES_FILTER, seriesFilter, dataContext);
// Add the flag defining whether only controller series are displayed
final boolean showControllerSeriesOnly = exportCfg.showControllerSeriesOnly();
addToContext(DATA_CTX_SHOW_CONTROLLERS_ONLY, showControllerSeriesOnly, dataContext);
JsonizerVisitor jsonizer = new JsonizerVisitor();
Map<String, Object> storedData = context.getData();
// Add begin date consumer result to the data context
addResultToContext(ReportGenerator.BEGIN_DATE_CONSUMER_NAME, storedData, dataContext, jsonizer);
// Add end date summary consumer result to the data context
addResultToContext(ReportGenerator.END_DATE_CONSUMER_NAME, storedData, dataContext, jsonizer);
// Add Apdex summary consumer result to the data context
addResultToContext(ReportGenerator.APDEX_SUMMARY_CONSUMER_NAME, storedData, dataContext, jsonizer);
// Add errors summary consumer result to the data context
addResultToContext(ReportGenerator.ERRORS_SUMMARY_CONSUMER_NAME, storedData, dataContext, jsonizer);
// Add requests summary consumer result to the data context
addResultToContext(ReportGenerator.REQUESTS_SUMMARY_CONSUMER_NAME, storedData, dataContext, jsonizer);
// Add statistics summary consumer result to the data context
addResultToContext(ReportGenerator.STATISTICS_SUMMARY_CONSUMER_NAME, storedData, dataContext, jsonizer);
// Add Top 5 errors by sampler consumer result to the data context
addResultToContext(ReportGenerator.TOP5_ERRORS_BY_SAMPLER_CONSUMER_NAME, storedData, dataContext, jsonizer);
// Collect graph results from sample context and transform them into
// Json strings to inject in the data context
ExtraOptionsResultCustomizer customizer = new ExtraOptionsResultCustomizer();
EmptyGraphChecker checker = new EmptyGraphChecker(filtersOnlySampleSeries, showControllerSeriesOnly, filterPattern);
Map<String, GraphConfiguration> mapConfiguration = new HashMap<>();
DataContext customGraphs = new DataContext();
for (Map.Entry<String, GraphConfiguration> graphEntry : configuration.getGraphConfigurations().entrySet()) {
final String graphId = graphEntry.getKey();
final GraphConfiguration graphConfiguration = graphEntry.getValue();
// Initialize customizer and checker
customizer.setExtraOptions(exportCfg.getGraphExtraConfigurations().get(graphId));
checker.setExcludesControllers(graphConfiguration.excludesControllers());
checker.setGraphId(graphId);
mapConfiguration.put(graphId, graphConfiguration);
if (graphId.startsWith(CUSTOM_GRAPH_PREFIX)) {
addResultToContext(graphId, storedData, customGraphs, jsonizer, customizer, checker);
} else {
// Export graph data
addResultToContext(graphId, storedData, dataContext, jsonizer, customizer, checker);
}
}
dataContext.put("graphConfigurations", mapConfiguration);
dataContext.put("customsGraphsData", customGraphs);
// Replace the begin date with its formatted string and store the old timestamp
long oldTimestamp = formatTimestamp(ReportGenerator.BEGIN_DATE_CONSUMER_NAME, dataContext);
// Replace the end date with its formatted string
formatTimestamp(ReportGenerator.END_DATE_CONSUMER_NAME, dataContext);
// Add time zone offset (that matches the begin date) to the context
TimeZone timezone = TimeZone.getDefault();
addToContext(DATA_CTX_TIMEZONE_OFFSET, timezone.getOffset(oldTimestamp), dataContext);
// Add report title to the context
if (StringUtils.isNotEmpty(configuration.getReportTitle())) {
dataContext.put(DATA_CTX_REPORT_TITLE, StringEscapeUtils.escapeHtml4(configuration.getReportTitle()));
}
// Add the test file name to the context
addToContext(DATA_CTX_TESTFILE, file.getName(), dataContext);
// Add the overall filter property to the context
addToContext(DATA_CTX_OVERALL_FILTER, configuration.getSampleFilter(), dataContext);
// Walk template directory to copy files and process templated ones
Configuration templateCfg = new Configuration(Configuration.VERSION_2_3_30);
try {
templateCfg.setDirectoryForTemplateLoading(templateDirectory);
templateCfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
if (log.isInfoEnabled()) {
log.info("Report will be generated in: {}, creating folder structure", outputDir.getAbsolutePath());
}
FileUtils.forceMkdir(outputDir);
TemplateVisitor visitor = new TemplateVisitor(templateDirectory.toPath(), outputDir.toPath(), templateCfg, dataContext);
Files.walkFileTree(templateDirectory.toPath(), visitor);
} catch (IOException ex) {
throw new ExportException("Unable to process template files.", ex);
}
log.debug("End of template processing");
}
use of org.apache.jmeter.report.config.GraphConfiguration in project jmeter by apache.
the class ReportGenerator method addGraphConsumer.
private void addGraphConsumer(FilterConsumer nameFilter, FilterConsumer excludeControllerFilter, Map.Entry<String, GraphConfiguration> entryGraphCfg) throws GenerationException {
String graphName = entryGraphCfg.getKey();
GraphConfiguration graphConfiguration = entryGraphCfg.getValue();
// Instantiate the class from the classname
String className = graphConfiguration.getClassName();
try {
Class<?> clazz = Class.forName(className);
Object obj = clazz.getDeclaredConstructor().newInstance();
AbstractGraphConsumer graph = (AbstractGraphConsumer) obj;
graph.setName(graphName);
// Set the graph title
graph.setTitle(graphConfiguration.getTitle());
// Set graph properties using reflection
Method[] methods = clazz.getMethods();
for (Map.Entry<String, String> entryProperty : graphConfiguration.getProperties().entrySet()) {
String propertyName = entryProperty.getKey();
String propertyValue = entryProperty.getValue();
String setterName = getSetterName(propertyName);
setProperty(className, obj, methods, propertyName, propertyValue, setterName);
}
graph.initialize();
// Choose which entry point to use to plug the graph
AbstractSampleConsumer entryPoint = graphConfiguration.excludesControllers() ? excludeControllerFilter : nameFilter;
entryPoint.addSampleConsumer(graph);
} catch (ClassNotFoundException ex) {
log.warn("Unable to add class:{} as consumer for HTML report generation, " + "check class name or that the plugin that contains it is on classpath", className, ex);
} catch (ClassCastException | IllegalArgumentException | ReflectiveOperationException | SecurityException ex) {
String error = String.format(INVALID_CLASS_FMT, className);
throw new GenerationException(error, ex);
}
}
Aggregations