diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentControllerBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentControllerBean.java index a49b12e09e5b332fadc95785f2d86472f1592cb2..c115ae7871a1fad873779f807cc4f4e2f36ec1e5 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentControllerBean.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentControllerBean.java @@ -292,7 +292,16 @@ public final class CurrentControllerBean { * * @return The current log entries. */ - public Collection<String> getLog() { + public Object[] getAnalysisLog() { + try { + return this.projectManagerFacade.getLogEntries(this.projectName); + } catch (final AnalysisStateException ex) { + // Ignore + return new Object[0]; + } + } + + public Collection<String> getViewLog() { return this.logEntries; } 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 2097e237742f9eab1eb5650664430b5d041b060b..267dd7f74b2e963e16678728b985ba960f4dbe42 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/common/ClassAndMethodContainer.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/common/ClassAndMethodContainer.java @@ -41,6 +41,7 @@ import kieker.analysis.repository.AbstractRepository; import kieker.analysis.repository.annotation.Repository; import kieker.common.logging.Log; import kieker.common.logging.LogFactory; +import kieker.common.logging.LogImplWebguiLogging; import kieker.webgui.common.exception.ProjectLoadException; /** @@ -63,6 +64,7 @@ public final class ClassAndMethodContainer { */ private static final String MSG_LOAD_EXCEPTION = "An error occured while loading the classes and methods."; + private final Class<?> logImplWebguiLoggingClass; /** * This is the class equivalence of {@link AnalysisControllerWithMapping}. */ @@ -224,6 +226,8 @@ public final class ClassAndMethodContainer { private final Method repositoryDependenciesMethod; private final Method pluginProgrammaticOnlyMethod; private final Method repositoryProgrammaticOnlyMethod; + private final Method logImplWebguiLoggingClassGetEntriesMethod; + /** * This is the constructor for {@link AnalysisControllerThread}, which gets an instance of {@link AnalysisController}. */ @@ -240,6 +244,8 @@ public final class ClassAndMethodContainer { @SuppressWarnings("unchecked") public ClassAndMethodContainer(final ClassLoader classLoader) throws ProjectLoadException { try { + this.logImplWebguiLoggingClass = classLoader.loadClass(LogImplWebguiLogging.class.getName()); + this.analysisControllerWithMappingClass = classLoader.loadClass(AnalysisControllerWithMapping.class.getName()); this.analysisControllerClass = classLoader.loadClass(AnalysisController.class.getName()); @@ -284,6 +290,8 @@ public final class ClassAndMethodContainer { this.repositoryDependenciesMethod = this.repositoryAnnotationClass.getMethod("dependencies", new Class<?>[0]); this.pluginProgrammaticOnlyMethod = this.pluginAnnotationClass.getMethod("programmaticOnly", new Class<?>[0]); this.repositoryProgrammaticOnlyMethod = this.repositoryAnnotationClass.getMethod("programmaticOnly", new Class<?>[0]); + this.logImplWebguiLoggingClassGetEntriesMethod = this.logImplWebguiLoggingClass.getMethod("getEntries", String.class); + // This is a special case as we need to load some additional classes to search for the correct method final Class<?> miProjectClass = classLoader.loadClass(MIProject.class.getName()); this.analysisControllerLoadFromFile = this.analysisControllerClass.getMethod("loadFromFile", File.class); @@ -711,6 +719,14 @@ public final class ClassAndMethodContainer { return this.repositoryProgrammaticOnlyMethod; } + public Class<?> getLogImplWebguiLoggingClass() { + return this.logImplWebguiLoggingClass; + } + + public Method getLogImplWebguiLoggingClassGetEntriesMethod() { + return this.logImplWebguiLoggingClassGetEntriesMethod; + } + /** * This method can be used to invoke a given method with given parameters, without having to mind about the exceptions. If an exception occurs, the given default * value will be returned. diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/common/EnvironmentLoaderListener.java b/Kieker.WebGUI/src/main/java/kieker/webgui/common/EnvironmentLoaderListener.java new file mode 100644 index 0000000000000000000000000000000000000000..e80a11265316afd1207321f01b1a48caab294807 --- /dev/null +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/common/EnvironmentLoaderListener.java @@ -0,0 +1,35 @@ +/*************************************************************************** + * Copyright 2012 Kieker Project (http://kieker-monitoring.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ + +package kieker.webgui.common; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +public class EnvironmentLoaderListener implements ServletContextListener { + + @Override + public void contextDestroyed(final ServletContextEvent event) { + // No code necessary + } + + @Override + public void contextInitialized(final ServletContextEvent event) { + // Set the system property to make sure that the webgui logger will be used + System.setProperty("kieker.common.logging.Log", "WEBGUI"); + } + +} diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/common/IProjectManagerFacade.java b/Kieker.WebGUI/src/main/java/kieker/webgui/common/IProjectManagerFacade.java index 99b7d621a9944b4042524efcdb316b206ce11c14..ea8c5fac07fa380091d85b5aa342a65eecf3d42a 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/common/IProjectManagerFacade.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/common/IProjectManagerFacade.java @@ -336,4 +336,5 @@ public interface IProjectManagerFacade { */ public STATE getCurrentState(final String projectName) throws ProjectNotExistingException; + public Object[] getLogEntries(final String projectName) throws AnalysisStateException; } diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/common/ProjectManagerFacade.java b/Kieker.WebGUI/src/main/java/kieker/webgui/common/ProjectManagerFacade.java index 13d3bb9a52ba4a6e47fa1919e11153ebfd65f754..c9e22cf7df527012896a08d2b748b2c0d6f8113b 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/common/ProjectManagerFacade.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/common/ProjectManagerFacade.java @@ -309,4 +309,13 @@ public final class ProjectManagerFacade implements IProjectManagerFacade { return lock; } + + @Override + public Object[] getLogEntries(final String projectName) throws AnalysisStateException { + final Object analysisLock = this.getLock(projectName, this.analysesLocks); + + synchronized (analysisLock) { + return ACManager.getInstance().getLogEntries(projectName); + } + } } diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/common/util/ACManager.java b/Kieker.WebGUI/src/main/java/kieker/webgui/common/util/ACManager.java index adca14b7473bab85166e00e33978e6cb3801668a..469c7ade95f2c866a7d421fdef1e7b58e3adcabc 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/common/util/ACManager.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/common/util/ACManager.java @@ -148,6 +148,14 @@ public final class ACManager { analysis.stop(); } + public Object[] getLogEntries(final String projectName) throws AnalysisStateException { + // The analysis for the given project must exist! + if (!this.analyses.containsKey(projectName)) { + throw new AnalysisStateException("The analysis has not been initialized yet."); + } + return this.analyses.get(projectName).getLogEntries(); + } + /** * This method delivers the display object of the (currently running) analysis for the given project and the given parameters. Technically it is an instance of * {@code AbstractDisplay}, but in fact the project specific class loader has been used. diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/common/util/Analysis.java b/Kieker.WebGUI/src/main/java/kieker/webgui/common/util/Analysis.java index 37a97b1d442f196c67a35b58a8a22555f815558d..91302501f1946775a45de87f1167e509d9c2de5b 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/common/util/Analysis.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/common/util/Analysis.java @@ -24,6 +24,7 @@ import java.util.concurrent.ConcurrentHashMap; import javax.annotation.PostConstruct; +import kieker.analysis.AnalysisController; import kieker.common.logging.Log; import kieker.common.logging.LogFactory; import kieker.webgui.common.ClassAndMethodContainer; @@ -154,6 +155,11 @@ public final class Analysis { return this.updateDisplaysThread.getDisplay(viewName, displayName); } + public Object[] getLogEntries() { + return (Object[]) ClassAndMethodContainer.invokeClassMethod(Analysis.this.classAndMethodContainer.getLogImplWebguiLoggingClassGetEntriesMethod(), null, + AnalysisController.class.getName()); + } + /** * This manager is responsible for the currently used and running instances of {@code AnalysisController}. It supplies methods to check the states of analysis, * instantiate, start and to stop them. @@ -161,7 +167,7 @@ public final class Analysis { * @author Nils Christian Ehmke * @version 1.0 */ - private static class UpdateDisplaysThread extends Thread { + private class UpdateDisplaysThread extends Thread { private static final long SLEEP_TIME_MS = 2 * 1000; // private final Object pluginMap; diff --git a/Kieker.WebGUI/src/main/resources/lang/ControllerPage_de.properties b/Kieker.WebGUI/src/main/resources/lang/ControllerPage_de.properties index 1fbc8559258aca5d3855aff479edfc26fdbcd8ee..cec041b923abc6460a4fff0054ec377bb33969c1 100644 --- a/Kieker.WebGUI/src/main/resources/lang/ControllerPage_de.properties +++ b/Kieker.WebGUI/src/main/resources/lang/ControllerPage_de.properties @@ -13,4 +13,9 @@ analysisControllerStopAnalysis = Analyse Stoppen analysisControllerMsgNotInstantiated = Zeigt an, dass der AnalysisController noch nicht instanziiert wurde. analysisControllerMsgReady = Zeigt an, dass der AnalysisController zwar instanziiert, jedoch noch nicht gestartet wurde. analysisControllerMsgRunning = Zeigt an, dass der AnalysisController gestartet wurde und zur Zeit läuft. -analysisControllerMsgFailed = Zeigt an, dass der AnalysisController terminiert oder abgestürzt ist. \ No newline at end of file +analysisControllerMsgFailed = Zeigt an, dass der AnalysisController terminiert oder abgestürzt ist. + +control = Steuerung + +analysisControllerLog = AnalysisController Log +personalLog = Persönlicher Log \ No newline at end of file diff --git a/Kieker.WebGUI/src/main/resources/lang/ControllerPage_en.properties b/Kieker.WebGUI/src/main/resources/lang/ControllerPage_en.properties index 589350fa3b3b62adda2fc7d1f3c224edf45ca4cb..30bb74895821e04544209a5649159566ff695373 100644 --- a/Kieker.WebGUI/src/main/resources/lang/ControllerPage_en.properties +++ b/Kieker.WebGUI/src/main/resources/lang/ControllerPage_en.properties @@ -13,4 +13,9 @@ analysisControllerStopAnalysis = Stop Analysis analysisControllerMsgNotInstantiated = Indicates that the AnalysisController has not been instantiated yet. analysisControllerMsgReady = Indicates that the AnalysisController has been instantiated, but not yet started. analysisControllerMsgRunning = Indicates that the AnalysisController has been started and is running. -analysisControllerMsgFailed = Indicates that the AnalysisController has been terminated or has failed. \ No newline at end of file +analysisControllerMsgFailed = Indicates that the AnalysisController has been terminated or has failed. + +control = Control + +analysisControllerLog = AnalysisController Log +personalLog = Personal Log \ No newline at end of file diff --git a/Kieker.WebGUI/src/main/webapp/ControllerPage.xhtml b/Kieker.WebGUI/src/main/webapp/ControllerPage.xhtml index ac4df2f674ed7feb19f9e37460ec34c35305ecc0..80bb824864d6587e4394f6893482ff85be0badcf 100644 --- a/Kieker.WebGUI/src/main/webapp/ControllerPage.xhtml +++ b/Kieker.WebGUI/src/main/webapp/ControllerPage.xhtml @@ -68,20 +68,31 @@ <p:layoutUnit position="center" id="centerLayout"> - <h:form id="logList"> - <ui:repeat value="#{currentControllerBean.log}" var="entry"> - <h:outputText value="#{entry}"/><br/><br/> - </ui:repeat> - </h:form> + <p:tabView id="tabView" style="height: 99%"> + <p:tab title="#{localizedControllerPageMessages.personalLog}"> + <h:form id="currentViewLog"> + <ui:repeat value="#{currentControllerBean.viewLog}" var="entry" varStatus="stat"> + <h:outputText value="#{entry}"/><ui:fragment rendered="#{not stat.last}"><br/><br/></ui:fragment> + </ui:repeat> + </h:form> + </p:tab> + <p:tab title="#{localizedControllerPageMessages.analysisControllerLog}"> + <h:form id="analysisControllerLog"> + <ui:repeat value="#{currentControllerBean.analysisLog}" var="entry" varStatus="stat"> + <h:outputText value="#{entry}"/><ui:fragment rendered="#{not stat.last}"><br/><br/></ui:fragment> + </ui:repeat> + </h:form> + </p:tab> + </p:tabView> </p:layoutUnit> - <p:layoutUnit position="south" header="Control" resizable="true" collapsible="true"> + <p:layoutUnit position="south" header="#{localizedControllerPageMessages.control}" resizable="true" collapsible="true"> <h:form id="controllerForm"> - <p:commandButton value="#{localizedControllerPageMessages.analysisControllerInstantiateAnalysisController}" action="#{currentControllerBean.instantiateAnalysis()}" update=":messages :logList" disabled="#{empty currentControllerBean.projectName}"/> - <p:commandButton value="#{localizedControllerPageMessages.analysisControllerCleaAnalysisController}" action="#{currentControllerBean.cleanAnalysis()}" update=":messages :logList" disabled="#{empty currentControllerBean.projectName}"/> - <p:commandButton value="#{localizedControllerPageMessages.analysisControllerStartAnalysis}" action="#{currentControllerBean.startAnalysis()}" update=":messages :logList" disabled="#{empty currentControllerBean.projectName}"/> - <p:commandButton value="#{localizedControllerPageMessages.analysisControllerStopAnalysis}" action="#{currentControllerBean.stopAnalysis()}" update=":messages :logList" disabled="#{empty currentControllerBean.projectName}"/> - <p:poll interval="1" update=":ledsForm"/> + <p:commandButton value="#{localizedControllerPageMessages.analysisControllerInstantiateAnalysisController}" action="#{currentControllerBean.instantiateAnalysis()}" update=":messages :tabView:currentViewLog" disabled="#{empty currentControllerBean.projectName}"/> + <p:commandButton value="#{localizedControllerPageMessages.analysisControllerCleaAnalysisController}" action="#{currentControllerBean.cleanAnalysis()}" update=":messages :tabView:currentViewLog" disabled="#{empty currentControllerBean.projectName}"/> + <p:commandButton value="#{localizedControllerPageMessages.analysisControllerStartAnalysis}" action="#{currentControllerBean.startAnalysis()}" update=":messages :tabView:currentViewLog" disabled="#{empty currentControllerBean.projectName}"/> + <p:commandButton value="#{localizedControllerPageMessages.analysisControllerStopAnalysis}" action="#{currentControllerBean.stopAnalysis()}" update=":messages :tabView:currentViewLog" disabled="#{empty currentControllerBean.projectName}"/> + <p:poll interval="1" update=":ledsForm :tabView:analysisControllerLog"/> </h:form> <hr/> <h:form id="ledsForm"> diff --git a/Kieker.WebGUI/src/main/webapp/WEB-INF/web.xml b/Kieker.WebGUI/src/main/webapp/WEB-INF/web.xml index 57f2cbabaf907bbdbb2fe5338cc094f10d46ee6d..f296c05d880fb51b706a8c2725550940933d5235 100644 --- a/Kieker.WebGUI/src/main/webapp/WEB-INF/web.xml +++ b/Kieker.WebGUI/src/main/webapp/WEB-INF/web.xml @@ -92,4 +92,7 @@ <dispatcher>ERROR</dispatcher> </filter-mapping> + <listener> + <listener-class>kieker.webgui.common.EnvironmentLoaderListener</listener-class> + </listener> </web-app>