package org.jboss.windup.reporting.rules.rendering;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.commons.io.FileUtils;
import org.jboss.windup.config.AbstractRuleProvider;
import org.jboss.windup.config.GraphRewrite;
import org.jboss.windup.config.loader.RuleLoaderContext;
import org.jboss.windup.config.metadata.RuleMetadata;
import org.jboss.windup.config.operation.GraphOperation;
import org.jboss.windup.config.phase.PostFinalizePhase;
import org.jboss.windup.graph.model.WindupConfigurationModel;
import org.jboss.windup.graph.model.performance.RulePhaseExecutionStatisticsModel;
import org.jboss.windup.graph.model.performance.RuleProviderExecutionStatisticsModel;
import org.jboss.windup.graph.service.GraphService;
import org.jboss.windup.graph.service.RuleProviderExecutionStatisticsService;
import org.jboss.windup.graph.service.WindupConfigurationService;
import org.jboss.windup.util.ExecutionStatistics;
import org.jboss.windup.util.PathUtil;
import org.jboss.windup.util.exception.WindupException;
import org.ocpsoft.rewrite.config.Configuration;
import org.ocpsoft.rewrite.config.ConfigurationBuilder;
import org.ocpsoft.rewrite.context.EvaluationContext;
/**
* Produces a simple text report of how long each RuleProvider's rule took to execute, the time spent in each phase, and
* any other timing data that was been stored in {@link ExecutionStatistics}.
*
* @author <a href="mailto:jesse.sightler@gmail.com">Jesse Sightler</a>
*
* This is basically a reporting rule, but we execute it during finalize in order to also report on
* the time it took to generate reports.
*/
@RuleMetadata(phase = PostFinalizePhase.class)
public class ExecutionTimeReportRuleProvider extends AbstractRuleProvider
{
@Override
public Configuration getConfiguration(RuleLoaderContext ruleLoaderContext)
{
return ConfigurationBuilder.begin()
.addRule()
.perform(new GraphOperation()
{
@Override
public void perform(GraphRewrite event, EvaluationContext context)
{
WindupConfigurationModel cfg = WindupConfigurationService.getConfigurationModel(event.getGraphContext());
String outputDir = cfg.getOutputPath().getFilePath();
// create a directory for the output
Path statsDir = Paths.get(outputDir, "stats");
FileUtils.deleteQuietly(statsDir.toFile());
PathUtil.createDirectory(statsDir, "stats folder");
Path detailedExecutionStatsOutputPath = statsDir.resolve("detailed_stats.csv");
ExecutionStatistics.get().serializeTimingData(detailedExecutionStatsOutputPath);
Path ruleTimingOutputPath = statsDir.resolve("timing.txt");
try (FileWriter fw = new FileWriter(ruleTimingOutputPath.toFile()))
{
Iterable<RuleProviderExecutionStatisticsModel> ruleProviderStatModels =
new RuleProviderExecutionStatisticsService(event.getGraphContext()).findAllOrderedByIndex();
// rule execution timings
fw.write("-----------------------------------------------------------\n");
fw.write("Rule execution timings:\n\n");
for (RuleProviderExecutionStatisticsModel model : ruleProviderStatModels)
{
int ms = model.getTimeTaken();
fw.write(String.format("% 5d.%03d, %s\n", ms / 1000, ms % 1000, model.getRuleProviderID()));
}
fw.write("-----------------------------------------------------------\n\n");
// phase execution timings
fw.write("Phase execution timings:\n\n");
GraphService<RulePhaseExecutionStatisticsModel> statsByPhaseService =
new GraphService<>(event.getGraphContext(), RulePhaseExecutionStatisticsModel.class);
Iterable<RulePhaseExecutionStatisticsModel> rulePhaseStatModelIterable = statsByPhaseService.findAll();
List<RulePhaseExecutionStatisticsModel> rulePhaseStatModelList = new ArrayList<>();
for (RulePhaseExecutionStatisticsModel model : rulePhaseStatModelIterable)
{
rulePhaseStatModelList.add(model);
}
Collections.sort(rulePhaseStatModelList, RulePhaseExecutionStatisticsModel.BY_ORDER_EXECUTED);
for (RulePhaseExecutionStatisticsModel model : rulePhaseStatModelList)
{
int ms = model.getTimeTaken();
fw.write(String.format("% 6d.%03d, %s\n", ms / 1000, ms % 1000, model.getRulePhase()));
}
fw.write("-----------------------------------------------------------\n");
}
catch (IOException e)
{
throw new WindupException("Error creating output file: " + ruleTimingOutputPath
+ " due to: " + e.getMessage(), e);
}
}
@Override
public String toString()
{
return "RenderRuleExecutionTimeReport";
}
});
}
}