All Downloads are FREE. Search and download functionalities are using the official Maven repository.

us.abstracta.jmeter.javadsl.dashboard.DashboardVisualizer Maven / Gradle / Ivy

Go to download

Module which includes listener for showing live dashboard window with graphs and stats.

There is a newer version: 028
Show newest version
package us.abstracta.jmeter.javadsl.dashboard;

import java.awt.Component;
import java.awt.GraphicsEnvironment;
import java.awt.GridLayout;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import kg.apc.charting.GraphPanelChart;
import kg.apc.jmeter.graphs.AbstractGraphPanelVisualizer;
import kg.apc.jmeter.graphs.AbstractOverTimeVisualizer;
import kg.apc.jmeter.vizualizers.ResponseCodesPerSecondGui;
import kg.apc.jmeter.vizualizers.ResponseTimesOverTimeGui;
import kg.apc.jmeter.vizualizers.ThreadsStateOverTimeGui;
import kg.apc.jmeter.vizualizers.TransactionsPerSecondGui;
import org.apache.jmeter.reporters.AbstractListenerElement;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.visualizers.SummaryReport;
import org.apache.jmeter.visualizers.Visualizer;
import org.apache.jmeter.visualizers.gui.AbstractVisualizer;
import org.apache.jorphan.collections.HashTree;
import org.apache.jorphan.gui.NumberRenderer;
import us.abstracta.jmeter.javadsl.core.BuildTreeContext;
import us.abstracta.jmeter.javadsl.core.listeners.DslVisualizer;

/**
 * Shows a popup window including live graphs and stats using JMeter built-in Summary Report and
 * graphs plugins.
 * 

* If dashboardVisualizer is added at testPlan level it will show information about all samples in * the test plan, if added at thread group level it will only show info for samplers contained * within it, if added as a sampler child, then only that sampler samples will be shown. * * @since 0.23 */ public class DashboardVisualizer extends DslVisualizer { public DashboardVisualizer() { super(null, null); } public static DashboardVisualizer dashboardVisualizer() { return new DashboardVisualizer(); } @Override public HashTree buildTreeUnder(HashTree parent, BuildTreeContext context) { if (GraphicsEnvironment.isHeadless()) { logNonGuiExecutionWarning(); return parent; } List graphs = Arrays.asList(new ThreadsStateOverTimeGui(), new ResponseTimesOverTimeGui(), new TransactionsPerSecondGui(), new ResponseCodesPerSecondGui()); graphs.forEach(g -> parent.add(buildGraphTestElement(g, context))); SummaryReport summary = new SummaryReport(); parent.add(buildVisualizerTestElement(summary, v -> v.getComponent(1), 0, context)); context.addVisualizer(this, () -> buildGui(graphs, summary)); return parent; } private TestElement buildGraphTestElement(AbstractOverTimeVisualizer graph, BuildTreeContext buildContext) { GraphPanelChart graphPanelChart = graph.getGraphPanelChart(); graphPanelChart.setxAxisLabelRenderer(new RelativeMinutesTimeRenderer()); // we set this to false to avoid AbstractOverTimeVisualizer overwriting our custom renderer graphPanelChart.getChartSettings().setUseRelativeTime(false); return buildVisualizerTestElement(graph, v -> ((AbstractGraphPanelVisualizer) v).getGraphPanelChart(), 500, buildContext); } private static final class RelativeMinutesTimeRenderer extends NumberRenderer { private long firstVal; @Override public void setValue(Object value) { setText(buildTimeString(value)); } private String buildTimeString(Object value) { if (value == null) { return ""; } else { if (value instanceof Double) { value = Math.round((Double) value); } firstVal = firstVal == 0 ? (long) value : Math.min(firstVal, (long) value); Duration time = Duration.ofMillis((long) value - firstVal); return String.format("%02d:%02d", time.toMinutes(), time.getSeconds() % 60); } } } public TestElement buildVisualizerTestElement(AbstractVisualizer visualizer, Function subComponentLocator, int repaintIntervalMillis, BuildTreeContext context) { AbstractListenerElement testElement = (AbstractListenerElement) visualizer.createTestElement(); visualizer.configure(testElement); Component subComponent = subComponentLocator.apply(visualizer); Visualizer rePainter = buildSubComponentRePainter(visualizer, subComponent, repaintIntervalMillis); testElement.setListener(rePainter); /* we need to add it to the root context to avoid losing reference and being null while sampling due to weak reference of test element listeners */ context.getRoot().getOrCreateEntry(getClass().getSimpleName(), ArrayList::new).add(rePainter); return testElement; } private Visualizer buildSubComponentRePainter(AbstractVisualizer delegate, Component subComponent, long repaintIntervalMillis) { return new Visualizer() { private long lastRepaint; @Override public void add(SampleResult sample) { delegate.add(sample); if (repaintIntervalMillis <= 0) { subComponent.repaint(); } else { long now = System.currentTimeMillis(); if (now - lastRepaint >= repaintIntervalMillis) { subComponent.repaint(); lastRepaint = now; } } } @Override public boolean isStats() { return false; } }; } @Override protected TestElement buildTestElement() { return null; } protected Component buildGui(List graphs, SummaryReport summary) { JSplitPane ret = new JSplitPane(JSplitPane.VERTICAL_SPLIT, buildGraphsPanel(graphs), buildSummaryPanel(summary)); ret.setResizeWeight(1.0); return ret; } private JPanel buildGraphsPanel(List graphs) { JPanel graphsPanel = new JPanel(); graphsPanel.setLayout(new GridLayout(0, 2)); graphs.forEach(g -> graphsPanel.add(g.getGraphPanelChart())); return graphsPanel; } private Component buildSummaryPanel(SummaryReport summary) { return summary.getComponent(1); } @Override public void showTestElementGui(Component guiComponent, Runnable closeListener) { showFrameWith(guiComponent, "Dashboard", 1080, 600, closeListener); } @Override public void showInGui() { throw new UnsupportedOperationException("Dashboard has no built-in JMeter GUI"); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy