From 4034008c1035cd0fd74bf80f9f5e1d1831056bcd Mon Sep 17 00:00:00 2001 From: Nils Christian Ehmke <nie@informatik.uni-kiel.de> Date: Sun, 2 Jun 2013 11:20:40 +0200 Subject: [PATCH] Added the meter gauge display. --- .../Bookstore-Example/Bookstore-Example.kax | 15 ++++- .../Timer-Counter-Example.kax | 6 +- .../bin/data/Timer-Counter-Example/meta.dat | 6 +- .../common/ClassAndMethodContainer.java | 7 +++ .../kieker/webgui/domain/DisplayType.java | 4 +- .../webgui/service/impl/utility/Analysis.java | 6 +- .../web/beans/view/CurrentCockpitBean.java | 63 +++++++++++++++++++ .../main/webapp/pages/ControllerPage.xhtml | 2 +- .../Class2ModelInstanceConverterTest.java | 2 +- 9 files changed, 100 insertions(+), 11 deletions(-) diff --git a/Kieker.WebGUI/bin/data/Bookstore-Example/Bookstore-Example.kax b/Kieker.WebGUI/bin/data/Bookstore-Example/Bookstore-Example.kax index a48eb3ed..63d0692a 100644 --- a/Kieker.WebGUI/bin/data/Bookstore-Example/Bookstore-Example.kax +++ b/Kieker.WebGUI/bin/data/Bookstore-Example/Bookstore-Example.kax @@ -18,19 +18,28 @@ <plugins xsi:type="Filter" name="Invalid Counter" classname="kieker.analysis.plugin.filter.forward.CountingFilter"> <outputPorts name="relayedEvents" subscribers="//@plugins.2/@inputPorts.0"/> <outputPorts name="currentEventCount"/> + <displays name="Visual Counter Display"/> <displays name="Counter Display"/> + <displays name="XYPlot Counter Display"/> + <displays name="Meter Gauge Counter Display"/> <inputPorts name="inputEvents"/> </plugins> <plugins xsi:type="Filter" name="Valid Counter" classname="kieker.analysis.plugin.filter.forward.CountingFilter"> <outputPorts name="relayedEvents" subscribers="//@plugins.6/@inputPorts.0"/> <outputPorts name="currentEventCount"/> + <displays name="Visual Counter Display"/> <displays name="Counter Display"/> + <displays name="XYPlot Counter Display"/> + <displays name="Meter Gauge Counter Display"/> <inputPorts name="inputEvents"/> </plugins> <plugins xsi:type="Filter" name="Global Counter" classname="kieker.analysis.plugin.filter.forward.CountingFilter"> <outputPorts name="relayedEvents" subscribers="//@plugins.1/@inputPorts.0"/> <outputPorts name="currentEventCount"/> + <displays name="Visual Counter Display"/> <displays name="Counter Display"/> + <displays name="XYPlot Counter Display"/> + <displays name="Meter Gauge Counter Display"/> <inputPorts name="inputEvents"/> </plugins> <plugins xsi:type="Filter" name="Valid Printer" classname="kieker.examples.userguide.ch3and4bookstore.MyResponseTimeOutputPrinter"> @@ -40,9 +49,9 @@ <dependencies filePath="BookstoreApplication.jar"/> <dependencies filePath="commons-cli-1.2.jar"/> <views name="Counter View" description="Shows the available counters"> - <displayConnectors name="Invalid Counter" display="//@plugins.3/@displays.0"/> - <displayConnectors name="Invalid Counter" display="//@plugins.4/@displays.0"/> - <displayConnectors name="Global Counter" display="//@plugins.5/@displays.0"/> + <displayConnectors name="Invalid Counter" display="//@plugins.3/@displays.1"/> + <displayConnectors name="Invalid Counter" display="//@plugins.4/@displays.1"/> + <displayConnectors name="Global Counter" display="//@plugins.5/@displays.1"/> </views> <properties name="recordsTimeUnit" value="NANOSECONDS"/> <properties name="projectName" value="AnalysisProject"/> diff --git a/Kieker.WebGUI/bin/data/Timer-Counter-Example/Timer-Counter-Example.kax b/Kieker.WebGUI/bin/data/Timer-Counter-Example/Timer-Counter-Example.kax index 069b4511..ac222a44 100644 --- a/Kieker.WebGUI/bin/data/Timer-Counter-Example/Timer-Counter-Example.kax +++ b/Kieker.WebGUI/bin/data/Timer-Counter-Example/Timer-Counter-Example.kax @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <Project xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="platform:/resource/Kieker/model/AnalysisMetaModel.ecore"> <plugins xsi:type="Reader" name="TimeReader" classname="kieker.analysis.plugin.reader.timer.TimeReader"> - <properties name="updateIntervalNS" value="2000000000"/> + <properties name="updateIntervalNS" value="1500000000"/> <properties name="delayNS" value="0"/> <properties name="blockingRead" value="true"/> <outputPorts name="timestamps" subscribers="//@plugins.4/@inputPorts.0"/> @@ -25,6 +25,7 @@ <displays name="Visual Counter Display"/> <displays name="Counter Display"/> <displays name="XYPlot Counter Display"/> + <displays name="Meter Gauge Counter Display"/> <inputPorts name="inputEvents"/> </plugins> <plugins xsi:type="Filter" name="Timestamps Counter" classname="kieker.analysis.plugin.filter.forward.CountingFilter"> @@ -33,6 +34,7 @@ <displays name="Visual Counter Display"/> <displays name="Counter Display"/> <displays name="XYPlot Counter Display"/> + <displays name="Meter Gauge Counter Display"/> <inputPorts name="inputEvents"/> </plugins> <views name="Counter View" description="No description available."> @@ -42,6 +44,8 @@ <displayConnectors name="Timestamps (Image)" display="//@plugins.4/@displays.0"/> <displayConnectors name="Timestamps (Text)" display="//@plugins.4/@displays.1"/> <displayConnectors name="Timestamps (Plot)" display="//@plugins.4/@displays.2"/> + <displayConnectors name="Timestamp Records (Meter Gauge)" display="//@plugins.3/@displays.3"/> + <displayConnectors name="Timestamps (Meter Gauge)" display="//@plugins.4/@displays.3"/> </views> <views name="Only Records View" description="No description available."> <displayConnectors name="Timestamp Records" display="//@plugins.3/@displays.1"/> diff --git a/Kieker.WebGUI/bin/data/Timer-Counter-Example/meta.dat b/Kieker.WebGUI/bin/data/Timer-Counter-Example/meta.dat index eee45730..8fbfbb64 100644 --- a/Kieker.WebGUI/bin/data/Timer-Counter-Example/meta.dat +++ b/Kieker.WebGUI/bin/data/Timer-Counter-Example/meta.dat @@ -1,6 +1,6 @@ # -#Fri May 31 19:58:26 CEST 2013 +#Sun Jun 02 11:24:25 CEST 2013 owner=admin -cockpit\ layout=0 0 0 1 0 2 1 0 1 1 1 2 0 0 last\ user=admin -analysis\ layout=id0 -615 -256 336 72;id1 -675 26 216 84;id2 59 -104 204 72;id3 59 26 204 72;id4 -305 38 396 84;id5 -305 -96 312 84;\#id1.0 id5.9 -535.5 25.5 -535.5 -84.5;id5.10 id2.2 -75.5 -96.5 -75.5 -92.5; +cockpit\ layout=0 0 0 1 0 2 1 0 1 1 1 2 0 3 1 3 0 0 +analysis\ layout=id0 -2221 -900 336 72;id1 -2281 -618 216 84;id2 -1547 -748 204 72;id3 -1547 -618 204 72;id4 -1911 -606 396 84;id5 -1911 -740 312 84;\#id1.0 id5.9 -2142.5 -619.5 -2142.5 -729.5;id5.10 id2.2 -1682.5 -741.5 -1682.5 -737.5; diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/common/ClassAndMethodContainer.java b/Kieker.WebGUI/src/main/java/kieker/webgui/common/ClassAndMethodContainer.java index f3a83404..9dab09ba 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/common/ClassAndMethodContainer.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/common/ClassAndMethodContainer.java @@ -22,6 +22,7 @@ import kieker.analysis.AnalysisController.AnalysisControllerWithMapping; import kieker.analysis.AnalysisControllerThread; import kieker.analysis.display.HtmlText; import kieker.analysis.display.Image; +import kieker.analysis.display.MeterGauge; import kieker.analysis.display.PlainText; import kieker.analysis.display.XYPlot; import kieker.analysis.display.annotation.Display; @@ -64,6 +65,7 @@ public class ClassAndMethodContainer { private Class<?> plainTextClass; private Class<?> htmlTextClass; private Class<?> xyPlotClass; + private Class<?> meterGaugeClass; private Class<? extends Annotation> pluginAnnotationClass; private Class<? extends Annotation> repositoryAnnotationClass; @@ -101,6 +103,7 @@ public class ClassAndMethodContainer { this.plainTextClass = classLoader.loadClass(PlainText.class.getName()); this.imageClass = classLoader.loadClass(Image.class.getName()); this.xyPlotClass = classLoader.loadClass(XYPlot.class.getName()); + this.meterGaugeClass = classLoader.loadClass(MeterGauge.class.getName()); // Now we load the more specific annotation classes this.pluginAnnotationClass = (Class<? extends Annotation>) classLoader.loadClass(Plugin.class.getName()); @@ -199,4 +202,8 @@ public class ClassAndMethodContainer { return this.xyPlotClass; } + public Class<?> getMeterGaugeClass() { + return this.meterGaugeClass; + } + } diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/domain/DisplayType.java b/Kieker.WebGUI/src/main/java/kieker/webgui/domain/DisplayType.java index 159a9287..ec93aa5b 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/domain/DisplayType.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/domain/DisplayType.java @@ -30,6 +30,8 @@ public enum DisplayType { /** Represents the Html text display type. */ TYPE_HTML_TEXT, /** Represents the image display type. */ - TYPE_IMAGE + TYPE_IMAGE, + /** Represents the meter gauge display type. */ + TYPE_METER_GAUGE } diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/utility/Analysis.java b/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/utility/Analysis.java index 7b60ea7e..919e3ae2 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/utility/Analysis.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/utility/Analysis.java @@ -23,6 +23,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import kieker.analysis.AnalysisController; import kieker.common.logging.Log; import kieker.common.logging.LogFactory; import kieker.webgui.common.ClassAndMethodContainer; @@ -198,7 +199,8 @@ public class Analysis { */ public Object[] getLogEntries() { try { - return (Object[]) new Mirror().on(this.classAndMethodContainer.getLogImplWebguiLoggingClass()).invoke().method("getEntries").withoutArgs(); + return (Object[]) new Mirror().on(this.classAndMethodContainer.getLogImplWebguiLoggingClass()).invoke().method("getEntries") + .withArgs(AnalysisController.class.getName()); } catch (final MirrorException ex) { return new Object[0]; } @@ -241,6 +243,8 @@ public class Analysis { return DisplayType.TYPE_HTML_TEXT; } else if (parameter.getClass() == this.classAndMethodContainer.getXYPlotClass()) { return DisplayType.TYPE_XY_PLOT; + } else if (parameter.getClass() == this.classAndMethodContainer.getMeterGaugeClass()) { + return DisplayType.TYPE_METER_GAUGE; } else { return null; } diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentCockpitBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentCockpitBean.java index cb2b991c..5ea90eaf 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentCockpitBean.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentCockpitBean.java @@ -16,6 +16,7 @@ package kieker.webgui.web.beans.view; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -42,6 +43,7 @@ import kieker.webgui.web.beans.application.ProjectsBean; import kieker.webgui.web.utility.CockpitLayout; import org.primefaces.component.chart.line.LineChart; +import org.primefaces.component.chart.metergauge.MeterGaugeChart; import org.primefaces.component.dashboard.Dashboard; import org.primefaces.component.panel.Panel; import org.primefaces.model.DashboardColumn; @@ -50,6 +52,7 @@ import org.primefaces.model.DefaultDashboardColumn; import org.primefaces.model.DefaultDashboardModel; import org.primefaces.model.chart.CartesianChartModel; import org.primefaces.model.chart.LineChartSeries; +import org.primefaces.model.chart.MeterGaugeChartModel; import net.vidageek.mirror.dsl.Mirror; import net.vidageek.mirror.exception.MirrorException; @@ -272,6 +275,9 @@ public class CurrentCockpitBean { case TYPE_XY_PLOT: this.updateXYPlotDisplay(component, displayConnector.getName()); break; + case TYPE_METER_GAUGE: + this.updateMeterGaugeDisplay(component, displayConnector.getName()); + break; default: // Unknown type this.updateDisplayWithDefaultContent(component); @@ -427,6 +433,63 @@ public class CurrentCockpitBean { } } + @SuppressWarnings("unchecked") + private void updateMeterGaugeDisplay(final UIComponent component, final String displayConnectorName) { + final boolean isAlreadyCorrectlyInitialized = (component.getChildCount() == 1) && (component.getChildren().get(0) instanceof MeterGaugeChart); + + final MeterGaugeChartModel meterGaugeChartModel; + + // Avoid unnecessary component creation. Use the existing components if they are already existing and from the correct type. + if (isAlreadyCorrectlyInitialized) { + final MeterGaugeChart meterGaugeChart = (MeterGaugeChart) component.getChildren().get(0); + meterGaugeChartModel = meterGaugeChart.getValue(); + } else { + final FacesContext facesContext = FacesContext.getCurrentInstance(); + final Application application = facesContext.getApplication(); + + // Create the Primefaces chart component + final MeterGaugeChart meterGaugeChart = (MeterGaugeChart) application.createComponent(facesContext, "org.primefaces.component.chart.MeterGaugeChart", + "org.primefaces.component.chart.MeterGaugeChartRenderer"); + meterGaugeChart.setTitle(displayConnectorName); + + // Add the corresponding model + meterGaugeChartModel = new MeterGaugeChartModel(); + meterGaugeChart.setValue(meterGaugeChartModel); + + component.getChildren().clear(); + component.getChildren().add(meterGaugeChart); + } + + try { + final Object displayObj = this.projectService.getDisplay(this.projectName, this.activeView.getName(), displayConnectorName); + + final List<Number> intervals = (List<Number>) new Mirror().on(displayObj).invoke().method("getIntervals").withoutArgs(); + final Number value = (Number) new Mirror().on(displayObj).invoke().method("getValue").withoutArgs(); + + if (intervals.isEmpty()) { + meterGaugeChartModel.setIntervals(Arrays.asList((Number) 50, 100)); + meterGaugeChartModel.setValue(0); + } else { + meterGaugeChartModel.setIntervals(intervals); + final Number maxInterval = intervals.get(intervals.size() - 1); + if (value.doubleValue() <= maxInterval.doubleValue()) { + meterGaugeChartModel.setValue(value); + } else { + meterGaugeChartModel.setValue(maxInterval); + } + } + } catch (final DisplayNotFoundException ex) { + CurrentCockpitBean.LOG.warn("Display not found.", ex); + this.updateDisplayWithDefaultContent(component); + } catch (final MirrorException ex) { + CurrentCockpitBean.LOG.warn("Reflection exception.", ex); + this.updateDisplayWithDefaultContent(component); + } catch (final InvalidAnalysisStateException ex) { + CurrentCockpitBean.LOG.info("Project is in invalid state.", ex); + this.updateDisplayWithDefaultContent(component); + } + } + @SuppressWarnings("unchecked") private void updateXYPlotDisplay(final UIComponent component, final String displayConnectorName) { final boolean isAlreadyCorrectlyInitialized = (component.getChildCount() == 1) && (component.getChildren().get(0) instanceof LineChart); diff --git a/Kieker.WebGUI/src/main/webapp/pages/ControllerPage.xhtml b/Kieker.WebGUI/src/main/webapp/pages/ControllerPage.xhtml index 2561ee44..f2a20143 100644 --- a/Kieker.WebGUI/src/main/webapp/pages/ControllerPage.xhtml +++ b/Kieker.WebGUI/src/main/webapp/pages/ControllerPage.xhtml @@ -52,7 +52,7 @@ </h:form> </p:panel> - <p:panel style="width: 100%; height:100%" header="#{localizedControllerPageMessages.analysisControllerLog}" collapsed="true"> + <p:panel style="width: 100%; height:100%" header="#{localizedControllerPageMessages.analysisControllerLog}"> <h:form id="analysisControllerLog" style="width: 100%"> <p:dataList value="#{currentControllerBean.analysisLog}" var="logEntry"> #{logEntry} diff --git a/Kieker.WebGUI/src/test/java/kieker/webgui/persistence/impl/utility/Class2ModelInstanceConverterTest.java b/Kieker.WebGUI/src/test/java/kieker/webgui/persistence/impl/utility/Class2ModelInstanceConverterTest.java index 3e3cb8cb..7f4ff0b8 100644 --- a/Kieker.WebGUI/src/test/java/kieker/webgui/persistence/impl/utility/Class2ModelInstanceConverterTest.java +++ b/Kieker.WebGUI/src/test/java/kieker/webgui/persistence/impl/utility/Class2ModelInstanceConverterTest.java @@ -124,7 +124,7 @@ public class Class2ModelInstanceConverterTest { final MIFilter filter = converter.convertFilterClass2ModelInstance(countingFilterCLass, classAndMethodContainer); Assert.assertEquals("Properties are not loaded correctly", countingFilterCLass.getCanonicalName(), filter.getClassname()); - Assert.assertEquals("Properties are not loaded correctly", 3, filter.getDisplays().size()); + Assert.assertEquals("Properties are not loaded correctly", 4, filter.getDisplays().size()); Assert.assertTrue("Properties are not loaded correctly", filter.getRepositories().isEmpty()); Assert.assertEquals("Properties are not loaded correctly", 2, filter.getOutputPorts().size()); Assert.assertEquals("Properties are not loaded correctly", 1, filter.getInputPorts().size()); -- GitLab