Most of the magic in a Team Build is done using either (a) customized tasks, or (b) a customized logger.  Well, most of the build machine magic - there's plenty of magic in the client, the Application Tier, and the Data Tier.  All right - even on the build machine I suppose plenty of magic happens within MSBuild itself.  In any case, we should be able to agree that some of the magic in a Team Build happens using customized tasks and loggers, right?  They're responsible for making most of the web service calls that populate the database with information about the build, interacting with source control and work item tracking, keeping track of the errors/warnings encountered during the build, etc.

Yesterday we looked at using tasks to add customized build steps during a build.  Today I'd like to show you how to add a customized logger...  For more information on MSBuild loggers, check out MSBuild Logging on MSDN.

Step 1.  Figure out why you want to add a logger. 

I was thinking about this last night - would a Team Build user ever want to add a custom logger?  The IDC team, implementers of Team Build 1.0, have a couple of posts on different types of custom loggers:

An XML Logger.  This might be useful for diagnostic purposes - it will show you every single event raised by MSBuild during the course of a build.  I wouldn't recommend it for large builds, unless you feel like filling up your hard disk!

An errors/warnings logger that creates log files per solution.  This could be pretty useful if you are running into tons of errors/warnings in your build and want to separate them out into more managable chunks (by default Team Build creates log files per configuration).

Neither of these seemed seemed particularly compelling to me, though - I could see wanting to use them once or twice, but not all the time.  How about this - out of the box TFS supports notifications on build completion or on build quality change.  For certain types of builds, though, one might want to send out notifications on build start.  Right?  Right?  Oh fine, it's not the most interesting thing in the world, but it's something...

If you come up with other interesting reasons to write your own loggers, please let me know!

Step 2.  You'll want to actually write your custom logger. 

I'm not going to post the entire sample this time - just the relevant bit. 

public class CustomLogger : ILogger
{
    ...
    public void Initialize(IEventSource source)
    {
        source.BuildStarted += new BuildStartedEventHandler(HandleBuildStartedEvent);
    }

    public void HandleBuildStartedEvent(Object sender, BuildStartedEventArgs args)
    {
        // Write fancy email sending code here!
    }
    ...
}

Step 3.  You'll need to tell MSBuild about your logger, using the /logger command-line switch. 

One of the files created for each build type is TfsBuild.rsp.  This is an MSBuild response file, and can contain MSBuild.exe command-line switches.  Team Build will pass this file to MSBuild.exe whenever a build is started (for the given build type). 

So - check out TfsBuild.rsp from source control, add something like the following:

/logger:CustomLogger,CustomLogger.dll

...and check it back in.

Step 4.  Make sure that your logger assembly is available during the build. 

The easiest thing here is probably to add it to the same directory in source control as the TfsBuild.rsp file you just modified - Team Build will then sync CustomLogger.dll along with TfsBuild.proj, TfsBuild.rsp, and WorkspaceMapping.xml.  In this case, you won't need to give a full path to the assembly in the rsp file, and the above example should just work.