Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Setting up CruiseControl.NET to be a Continuous Monitoring Server

4.68/5 (10 votes)
2 Sep 2008CPOL6 min read 5  
The aim of this article is to show how you can install, configure, and have CruiseControl.NET perform continuous monitoring by running a scheduled task.

Introduction

The aim of this article is to show how you can install, configure, and have CruiseControl.NET perform continuous monitoring by running a scheduled task.

Once you've seen the idea behind how to set everything up, it's quite easy to extend this concept to perform continuous monitoring on things such as:

  • Health monitoring for key systems (databases, Web services, etc.)
  • Report generation
  • Batch jobs
  • Content that is produced to be consumed via RSS or exported via FTP for other applications

In order for CruiseControl.NET to be useful as a monitoring server, you need to be able to:

  • Schedule tasks to occur at certain intervals, just like you would schedule a task in Windows using Cruise Control Triggers
  • Provide feedback to users on whether the task failed/passed, by merging output from the monitoring application to the build report page

This article will focus on combining the scheduling aspect with a simple program that monitors a URL.

Note: There are many ways you could achieve the monitoring of a URL; this example merely provides a way to show how you can take any console output and get it into the build report.

Required Software

You can download CruiseControl.NET 1.3 from here, and I've installed it with all the default options.

Note: CruiseControl 1.4 is the current latest release, this tutorial should work with it, although I haven't tested it yet.

NAnt will be used by CruiseControl.NET to run our console application. You can download NAnt 0.85 from here (nant-0.85-bin.zip) and then extract it to wherever your utils go.

Once you've installed CruiseControl.NET, the installation process should have configured a virtual directory called ccnet under your default website and installed and started the CruiseControl.NET service.

Check that all is running OK by going to http://localhost/ccnet. You should see the Web dashboard load, but with no projects configured.

Now, we are ready to:

  1. Create the simple console application to monitor a URL
  2. Configure and schedule CruiseControl.NET to run our application
  3. Display the console output in the build report

1. The Monitoring Application

The monitoring application is a simple console application which will return 0 or 1, depending on whether a check on a URL passes or fails.

The application writes out to the console some simple information on the status of checking the URL. Whatever the console application outputs will be stored as part of the NAnt build information and merged into the build report. If your program throws an exception that isn't caught, CruiseControl will assume a fail.

The C# code for the console application is as follows:

Program.cs

C#
using System;
using System.Net;

namespace MonitoringApplication
{
   class Program
   {
       static int Main(string[] args)
       {
           string url = args[0];
           string timestamp = DateTime.Now.ToString("HH:mm:ss ");
           try
           {
              WebRequest request = WebRequest.Create(url);
              HttpWebResponse response = (HttpWebResponse)request.GetResponse();
              Console.WriteLine(timestamp + "  Successfully connected to: "+ url);
              return 0;
           }
           catch (Exception ex)
           {
               Console.WriteLine(timestamp + "  Failed to connect to: "+ url);
               Console.WriteLine(timestamp + "  "+ ex.Message);
               return 1;
           }
       }
   }
}

2. Scheduling a Project in CruiseControl.NET

For our URL monitoring example, we would like to schedule a console application to run at certain times.

The following shows how to set up the <triggers> part of the <project> definition in ccnet.config, in order to achieve the following schedule:

  • The program will run Monday - Friday, between 8am and 6pm, every 15 minutes
  • Doesn't run on Saturdays and Sundays

You will need to specify your own <workingDirectory> in the config below; this directory should contain the application and the build file.

For further information on the <FilterTrigger>, see the documentation here, and more detailed information on the NAnt <task> can be found in the documentation here.

C:\Program Files\CruiseControl.NET\server\ccnet.config

XML
<cruisecontrol>
   <project name="Url Test">
       <workingDirectory>[specify your working directory]</workingDirectory>
       <triggers>
           <filterTrigger startTime="18:00" endTime="08:30">
               <trigger type="filterTrigger" startTime="0:00" endTime="23:59:59">
               <trigger type="intervalTrigger" name="continuous"
                        seconds="900" buildCondition="ForceBuild"/>
                   <weekDays>
                       <weekDay>Saturday</weekDay>
                       <weekDay>Sunday</weekDay>
                   </weekDays>
               </trigger>
           </filterTrigger>
       </triggers>
       <tasks>
           <nant>
               <executable>C:\Program Files\Utils\nant-0.85\bin\NAnt.exe</executable>
               <nologo>true</nologo>
               <buildFile>C:\dev\MonitoringApplication\bin\Debug\
                        urltest.build</buildFile>
               <targetList>
                   <target>UrlTest</target>
               </targetList>
               <buildTimeoutSeconds>300</buildTimeoutSeconds>
           </nant>
       </tasks>
   </project>
</cruisecontrol>

3. Creating the NAnt Build File to Run the Application

The <buildFile> that is referred to in the above file ccnet.config is what CruiseControl.NET will use to execute the console application. In the build file, I'm passing the URL I want to test via the command line parameter of the <exec> task.

For more information on NAnt files, click here, and in particular, the documentation on the <exec> task is here.

<whatever you have set the workingDirectory to>\urltest.build

XML
<?xml version="1.0" ?>
   <project name="Url.Test" default="UrlTest"
            xmlns="http://nant.sf.net/schemas/nant.xsd">
   <property name="root"  value="${path::get-full-path('.')}"/>
   <property name="name"  value="MonitoringApplication.exe"/>
   <target name="UrlTest">
      <exec verbose="true" append="true"
          output="urltest.log" program="${root}\${name}"
          commandline="http://www.yahoo.com" />
   </target>
</project>

You should now be able to see your project on the Web dashboard at http://localhost/ccnet and force a build to test the console application. Test using an invalid URL, and you should see similar output to the image below. You'll notice that on a failure, you are not told what was wrong, just that it failed.

Image 1

Next, we'll merge the console output into the build report for better error reporting.

CruiseControl.NET won't run my program or say there's some error, where can I find the build or NAnt log?
  1. The first thing to do is to check that your build file works correctly from a command prompt.
  2. Check the CruiseControl.NET build and the NAnt log files.. These can be accessed by clicking on the build you would like to inspect and selecting the appropriate link on the left.
  3. Image 2

  4. If you are using relative paths to your <workingDirectory> that you specified in the <project> part of the ccnet.config, try using the full path to eliminate any path errors.

4. Merging the Console Output into the Build Report Page

By default, the console application output is not included in the build report page. This doesn't matter so much when everything is working, but when the application fails, it would be nice to see what happened via the CruiseControl.NET web dashboard, without having to hunt through log files.

CruiseControl.NET has a list of extensible style sheets that will be applied to the build output. You can configure what is shown in the dashboard.config in the buildReportBuildPlugin section.

Below, you can see where I've added my own XSL file to style the console applications output:

C:\Program Files\CruiseControl.NET\webdashboard\dashboard.config

XML
<-- Snip -->
   <buildReportBuildPlugin>
      <xslFileNames>
         <xslFile>xsl\header.xsl</xslFile>
         <xslFile>xsl\ConsoleOutput.xsl</xslFile>
<-- Snip -->

Now, create a new file called ConsoleOuput.xsl and place it in C:\Program Files\CruiseControl.NET\webdashboard\xsl:

C:\Program Files\CruiseControl.NET\webdashboard\xsl\ConsoleOuput.xsl

XML
<?xml version="1.0"?>
<xsl:stylesheet  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:output method="html"/>

   <xsl:template match="/">
      <xsl:variable name="messages"
           select="/cruisecontrol//task[@name='exec']/message" />
      <xsl:variable name="messages.count" select="count($messages)" />

      <table class="section-table" cellpadding="2" cellspacing="0" border="0">
         <tr>
            <td colspan="2" class="sectionheader">Console Output</td>
         </tr>
         <tr>
            <td colspan="2" class="header-data">
               <xsl:choose>
                  <xsl:when test="$messages.count > 0">
                     <xsl:apply-templates select="$messages"/>
                  </xsl:when>
                  <xsl:otherwise>
                     No console output found
                  </xsl:otherwise>
               </xsl:choose>
            </td>
         </tr>
      </table>
   </xsl:template>

   <xsl:template match="message">
      <xsl:value-of select="text()"/><br/>
   </xsl:template>

</xsl:stylesheet>

An explanation of how XSL works is beyond the scope of the article, but I'll briefly discuss the highlight areas above:

  1. We setup our condition to extract the right elements from the build log file
  2. Create a variable to test if we have any messages to display
  3. If we have messages, apply our simple template to display each message

Note: You could make XML extraction smarter if your console application outputted a keyword per line and you only picked specific messages with that keyword.

Now, when the build fails, you'll get all the information that the console application generated.

Image 3

Remote Monitoring and Notification of Build Errors

Whenever the monitoring application fails, the results are easily available for any user via the CC.Net Web dashboard and those subscribed to the project using CCTray. CCTray can be downloaded from here, and allows users to subscribe to specific projects that they are interested in and be notified of the status.

Image 4

Image 5

Credit

This article was inspired by a Scott Hanselman's podcast - HanselMinutes, when he interviewed Owen Rogers regarding Continuous Monitoring.

Steve Trefethen has also created a customised solution using CruiseControl, which is part of an EDI Invoicing project he did; check out the article for some great ideas on what can be done.

Please contact me with any comments, suggestions, and feedback!

Revision History

2008-07-16

  • Article moved to The Code Project
  • Added Credit section
  • Moved XSL for application output into its own file and added this as build report plug-in
  • Changed article wording and layout

2008-06-09

  • Article published

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)