Displaying portlet monitoring information

Exposing well hidden features

Those of you who attended my "Well Hidden Features of Liferay" presentation at the 2012 european symposium might remember the well hidden monitoring information that LIferay is able to hide at the bottom of each page, in HTML comments (when configured properly). (You can also listen to the recording of this presentation on Radio Liferay) The slide that I used in the presentation was probably the one with the most text I ever used on any slide (the background is a beautified version of what you find on a page, the foreground is a beautified version of one line):

slide with the HTML comment (illustration)

I have created a very simple and straightforward plugin that will display the same information, well visible and organized at the bottom of the page - note that the configuration required remains the same. This is a sample output that you'll find at the bottom of each page with this plugin:

Name Namespace Description Duration User Status URL/DisplayName Timeout/Portlet Id Attributes Type
103 c.l.m.Portlet null 0 null SUCCESS Tags Compiler 103   RENDER
56 c.l.m.Portlet null 36 null SUCCESS Journal Content 56_INSTANCE_JaLJR3MQtAYm   RENDER
101 c.l.m.Portlet null 130 null SUCCESS Asset Publisher 101_INSTANCE_0BVmhEtIm8dR   RENDER
/h/c/t/portal.jsp c.l.m.Portal Portal Request 629 null SUCCESS .../portal.jsp.jsp_display -1  

There's nothing fancy except the abbreviations (in italics): If you hover the mouse over them, you'll see what they're abbreviated from. If you can make use if this information - e.g. to find performance bottlenecks in your plugins and pages - this might be valuable information right at your fingertip. Feel free to use this as a starting point and explore more interactive and better solutions to display this data. Or deploy this to your test environment and parse the output to test for a specific portlet's performance.

Where is it?

You can find this plugin in its own branch on github: The only "actual" file that changes anything is bottom_monitoring.jsp - in the interest of keeping the implementation in a simple hook, everything is contained in that jsp.

Documentation for the required configuration is included in its README.html (or see the raw version on github on github)

Blogs
I turned on monitoring, seems to be working on public pages , but failing on private pages.

java.lang.IllegalStateException: Stopwatch is not running.
org.apache.commons.lang.time.StopWatch.stop(StopWatch.java:142)
com.liferay.portal.monitoring.statistics.BaseDataSample.capture(BaseDataSample.java:35)
org.apache.jsp.html.common.themes.bottom_jsp._jspService(bottom_jsp.java:1877)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:72)
com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilter.doFilter(InvokerFilter.java:70)
com.liferay.taglib.util.VelocityTaglib.include(VelocityTaglib.java:377)
sun.reflect.GeneratedMethodAccessor433.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.apache.velocity.util.introspection.UberspectImpl$VelMethodImpl.doInvoke(UberspectImpl.java:389)
org.apache.velocity.util.introspection.UberspectImpl$VelMethodImpl.invoke(UberspectImpl.java:378)
org.apache.velocity.runtime.parser.node.ASTMethod.execute(ASTMethod.java:270)
org.apache.velocity.runtime.parser.node.ASTReference.execute(ASTReference.java:262)
org.apache.velocity.runtime.parser.node.ASTReference.render(ASTReference.java:342)
org.apache.velocity.runtime.parser.node.SimpleNode.render(SimpleNode.java:336)
org.apache.velocity.Template.merge(Template.java:328)
org.apache.velocity.Template.merge(Template.java:235)
org.apache.velocity.app.VelocityEngine.mergeTemplate(VelocityEngine.java:381)
com.liferay.portal.velocity.VelocityEngineImpl.mergeTemplate(VelocityEngineImpl.java:184)
com.liferay.portal.velocity.VelocityEngineImpl.mergeTemplate(VelocityEngineImpl.java:194)
com.liferay.portal.kernel.velocity.VelocityEngineUtil.mergeTemplate(VelocityEngineUtil.java:71)
com.liferay.taglib.util.ThemeUtil.includeVM(ThemeUtil.java:409)
com.liferay.taglib.util.ThemeUtil.include(ThemeUtil.java:99)
com.liferay.taglib.theme.IncludeTag.doEndTag(IncludeTag.java:39)
org.apache.jsp.html.common.themes.portal_jsp._jspx_meth_liferay_002dtheme_005finclude_005f1(portal_jsp.java:484)
org.apache.jsp.html.common.themes.portal_jsp._jspService(portal_jsp.java:429)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:72)
com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilter.doFilter(InvokerFilter.java:70)
com.liferay.portal.struts.StrutsUtil.include(StrutsUtil.java:135)
com.liferay.portal.struts.PortalRequestProcessor.doInclude(PortalRequestProcessor.java:289)
org.apache.struts.tiles.TilesRequestProcessor.processTilesDefinition(TilesRequestProcessor.java:237)
org.apache.struts.tiles.TilesRequestProcessor.processForwardConfig(TilesRequestProcessor.java:302)
org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:241)
com.liferay.portal.struts.PortalRequestProcessor.process(PortalRequestProcessor.java:174)
org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196)
org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:414)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
com.liferay.portal.servlet.MainServlet.callParentService(MainServlet.java:533)
com.liferay.portal.servlet.MainServlet.service(MainServlet.java:510)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:72)
com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:121)
com.liferay.portal.servlet.filters.monitoring.MonitoringFilter.processFilter(MonitoringFilter.java:78)