Dashboard > CruiseControl > TheCruiseControlJavaServerPage > CustomiseJSPReporting
CustomiseJSPReporting Log In View a printable version of the current page.

Added by Liam Friel , last edited by Liam Friel on Apr 02, 2007  (view change)
Labels: 
(None)

It's often quite useful to customise the web interface which can be used to present the build results and logs to the user.

And example of when this can be a good idea is if you are using CruiseControl to drive a legacy build environment (gmake/script based). In this case the default out-of-the-box Web interface does not present very useful information to you.

Doing this requires some knowledge of XSL/XSLT syntax and usage. While I'll present one example of implementing this in this entry, to fully understand XSL/XSLT you will need to study the topic a bit. A good tutorial on this can be found here but there are many on the web.

This Chapter refers to work which was done based on CruiseControl V2.5: I have not yet had a chance to look at V2.6 to see if it is still directly applicable. It's presented here as an example of how to extend the JSP interface, and it not intended to show you the best way, or the only way, to do this.

In general, the format the contents of the JSP/Web interface are defined in a collection of files which are found in the reporting/jsp/webcontent directory and sub-directories thereof. This directory we'll refer to as %WCR% in the following overviews.

In this short overview, we'll explain two changes to the default web output:

  • Adding a tab to the main reporting interface to show you "raw" log output
  • Processing the output from a non-ANT build to identify error or warning messages

Adding a Tab to the Reporting Interface

To add a tab to the reporting interface:

  • Edit the file %WCR%/main.jsp
  • Add a reference to the new tab, like so:
<cruisecontrol:tab name="buildOutput" label="Log File" >
  <%@ include file="op_logfile.jsp" %>
</cruisecontrol:tab>
  • Create the file op_logfile.jsp in the %WCR% directory. This file is just contains a reference to the XSL stylesheet to apply, e.g.
<%@ taglib uri="/WEB-INF/cruisecontrol-jsp11.tld" prefix="cruisecontrol"%>
<cruisecontrol:xsl xslFile="/xsl/op_logfile.xsl"/>
  • Create the op_logfile.xsl file in the %WCR%/xsl directory. This file contains the style rules to apply. For example:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:import href="raw_log_output.xsl" />
  <xsl:output method="html"/>

  <h2>Raw build log output</h2>
  <xsl:variable name="cruisecontrol.list" select="."/>

  <xsl:template match="/">

    <!-- Following S3-derived XSL just pretty-prints the raw build output -->
    <p><xsl:apply-templates select="$cruisecontrol.list" mode="raw_log_output"/></p>

  </xsl:template>
</xsl:stylesheet>

  • In the example above, we are referring to raw_log_output.xsl. Create this file in the %WCR%/xsl directory. This file contains:
<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://www.w3.org/TR/html4/strict.dtd" >

    <xsl:output method="html"/>

    <xsl:variable name="tasklist" select="/cruisecontrol/build/target/task"/>

    <xsl:template match="/" mode="raw_log_output">

     <xsl:variable name="messages" select="/cruisecontrol/build/target/task/message[@priority='info']"/>
     <xsl:variable name="message.count" select="count($messages)"/>

        <xsl:if test="$message.count > 0">
            <table align="center" cellpadding="2" cellspacing="0" border="0" width="98%">

                    <xsl:for-each select="$messages">
                    <tr>
						<xsl:if test="position() mod 2=0"><xsl:attribute name="class">modifications-oddrow</xsl:attribute> </xsl:if>
						<xsl:if test="position() mod 2!=0"><xsl:attribute name="class">modifications-evenrow</xsl:attribute> </xsl:if>
						<td class="compile-data">
						<xsl:value-of select="text()"/>
						</td>
					</tr>
                    </xsl:for-each>
            </table>
        </xsl:if>

    </xsl:template>

	<xsl:template match="/">
		<xsl:apply-templates select="." mode="raw_log_output"></xsl:apply-templates>
	</xsl:template>
</xsl:stylesheet>

  • A complete description of the above is beyond the scope of this Chapter (refer to XSL/XSLT references on the Web) but what is basically says is

"For every <message> entry in the raw XML output which is tagged as having priority "info", print out the contents of each into a table row. Apply different styles to odd and even rows to make them easier to see. Ignore all other lines in the Raw XML output."

I've attached the main files to this entry, to save you typing this in again.

  • Now rebuild your .war file as normal, and you should get the new tab added to your web interface.

Parsing standard gnu compiler output for Errors/Warnings

One of the things that can be very useful to do is parse the output from a "legacy" build tool. I'm putting "legacy" in quotes because in my experience the overwhelming majority of projects in certain sectors still use a make tool (such as gnu make) to drive their build environment, and a regular C/C++ compiler (like gcc) to build the software tree.

An issue with the out-of-the-box CruiseControl reporting applications is that they do not handle such a setup without some customisation.

In this section I'll show you how to parse the output from a gmake/gcc build to display sensible output on the reporting interface. The files mentioned in this section are attached as attachments, to save typing.

The format of the errors/warnings section of the web interface is controlled by %WCR%/main.jsp. You don't need to edit this file.
This list line of this file in the default installation just says:

<cruisecontrol:xsl xslFile="/xsl/buildresults.xsl"/>

i.e. "Go apply the style sheet in %WCR%/xsl/buildresults.xsl

  • Edit the file %WCR%/xsl/buildresults.xsl to add references to the GCC error formatter gcc_compile.xsl.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:import href="maven.xsl"/>
  <xsl:import href="nant.xsl"/>
  <xsl:import href="checkstyle.xsl"/>
  <xsl:import href="pmd.xsl"/>
  <xsl:import href="macker.xsl"/>
  <xsl:import href="gcc_compile.xsl"/>
  
  <xsl:import href="unittests.xsl"/>
  <xsl:import href="fittests.xsl"/>
  <xsl:import href="modifications.xsl"/>

  <xsl:output method="html"/>

  <xsl:variable name="cruisecontrol.list" select="."/>

  <xsl:template match="/">
    <p><xsl:apply-templates select="$cruisecontrol.list" mode="maven"/></p>
    <p><xsl:apply-templates select="$cruisecontrol.list" mode="nant"/></p>
    <p><xsl:apply-templates select="$cruisecontrol.list" mode="checkstyle"/></p>
    <p><xsl:apply-templates select="$cruisecontrol.list" mode="pmd"/></p>
    <p><xsl:apply-templates select="$cruisecontrol.list" mode="macker"/></p>
    
    <!-- Following S3-derived XSL shows how to parse make/C compiled output -->
    <p><xsl:apply-templates select="$cruisecontrol.list" mode="gcc_compile"/></p>

    <p><xsl:apply-templates select="$cruisecontrol.list" mode="unittests"/></p>
    <p><xsl:apply-templates select="$cruisecontrol.list" mode="fittests"/></p>
    <p><xsl:apply-templates select="$cruisecontrol.list" mode="modifications"/></p>
    
  </xsl:template>
</xsl:stylesheet>
  • Create the file gcc_compile.xsl in the directory %WCR%/xsl. This file is attached in it's entirely to this article. The interesting section is the filter which recognises an error or warning:
    <xsl:variable name="tasklist" select="/cruisecontrol/build/target/task"/>

    <xsl:template match="/" mode="gcc_compile"> 
     
     <xsl:variable name="javac.error.messages" select="cruisecontrol/build/target/task/message[@priority='error'][text() != '']"/>
     <xsl:variable name="javac.warn.messages" select="cruisecontrol/build/target/task/message[@priority='warn'][text() != '']"/>
     <xsl:variable name="make.error.messages" select="/cruisecontrol/build/target/task/message[@priority='info'][contains(text(),'***')]"/>
     <xsl:variable name="error.messages" select="/cruisecontrol/build/target/task/message[@priority='info'][contains(text(),'error:')]"/>
     <xsl:variable name="warn.messages" select="/cruisecontrol/build/target/task/message[@priority='info'][contains(text(),'warning:')]"/>

     . . .
  • A complete description of this file is beyond the scope of this Chapter, but what is basically says is:

    "For every <message> entry in the raw XML output which is tagged as having priority "info", define a filter make.error.messages which picks out those message entries containing the text "error:" "

  • It has similar rules for errors thrown by gmake itself (tagged with ***), and for warnings.
  • The file also has a output formatting section, similar to that in the first part of the Chapter. Here's a sample:
                <xsl:if test="$total.errorMessage.count > 0">
                    <xsl:for-each select="$error.messages">
                    <tr>
						<xsl:if test="position() mod 2=0"><xsl:attribute name="class">modifications-oddrow</xsl:attribute> </xsl:if>
						<xsl:if test="position() mod 2!=0"><xsl:attribute name="class">modifications-evenrow</xsl:attribute> </xsl:if>
						<td class="compile-error-data">
						<xsl:value-of select="text()"/>
						</td>
					</tr>
                    </xsl:for-each>                   
                    <xsl:for-each select="$make.error.messages">
                    <tr>
						<xsl:if test="position() mod 2=0"><xsl:attribute name="class">modifications-oddrow</xsl:attribute> </xsl:if>
						<xsl:if test="position() mod 2!=0"><xsl:attribute name="class">modifications-evenrow</xsl:attribute> </xsl:if>
						<td class="compile-error-data">
						<xsl:value-of select="text()"/>
						</td>
					</tr>
                    </xsl:for-each>                   
                </xsl:if>
  • Now rebuild your .war file as normal, and you should get the new output format in your web output.
  • You can clearly extend this to recognise any type of character string output in your build logs, and select those for display.
  • NB Cruise caches the web pages. If you have viewed the web page already, you will have to clear the cache in order to see the new content. The easiest way to do this is to delete the _cache directory or directories under your build log directories.
Powered by a free Atlassian Confluence Open Source Project / Non-profit License granted to ThoughtWorks, Inc.. Evaluate Confluence today.
Powered by Atlassian Confluence 2.7.1, the Enterprise Wiki. Bug/feature request - Atlassian news - Contact administrators