BizTalk and Enterprise Library: Logging Custom Components

Hi Folks,

This article is going to discuss how to use Enterprise Library and integrate it with BizTalk Components. The examples in this blog are based on a Pipeline component that I use to import flat files, you can easily convert the pipeline component to a file adapter, but the performance difference is negligible and is just a matter of preference. It is nice to make really robust application, but more importantly efficient caching, logging and exception handling is often missed! I assume the reader has in depth knowledge of Microsoft BizTalk 2006

First I create folders for Caching, Logging and Exception Handling in my current Pipeline Project.

 

 

The Decoders folder has the decoder components for a Pipeline

The Disassemblers folder has the disassemblers components for a Pipeline

The FileTranslator is a custom component that a disassemble component can call to transform flat files into XML using a custom configuration, this is not in scope of this blog and will be treated black box, in future blogs, I will discuss how to write such a component and it is far more powerful than using the BizTalk Mapper, since the BizTalk Mapper is only good for small schema’s when trandforms become complicated and many rules need to be applied, I recommend a custom file translator which you can implement as a File Adapter or Pipeline, does not really matter as long as you handle exceptions correctly and catch them and always treat you files in streams and use a recordline processing model so you never load the entire file in memory.

 

Requisites

Install Microsoft Enterprise Library 3.1 May 2007

http://www.microsoft.com/downloads/details.aspx?FamilyID=4c557c63-708f-4280-8f0c-637481c31718&displaylang=en

 

Logging

We are going to start setting up the Logging mechanism first.

  • Add a reference to the Project to Microsoft.Practices.EnterpriseLibrary.Logging, I like to create an External Assemblies folders, so when deployment occurs, I remember to add it to the GAC. I add the dll from the install folder e.g. D:\Program Files\Microsoft Enterprise Library 3.1 – May 2007\Bin to my own project, that way, external dll’s are never lost.

  • Add a using statement for Microsoft.Practices.EnterpriseLibrary.Logging
  • Create a public, serializable class in the Logging folder and add a method that accepts two strings.

using System;

using Microsoft.Practices.EnterpriseLibrary.Logging;

 

namespace MMIT.BizTalk.Components.Pipelines.Logging

{

 

[Serializable]

public class LogManager

{

public static void Log(string message, string category)

{

Logger.Write(message, category);

}

 

}

}

 

  • The next step is to implement the configuration file for this. Things to note, usually when you have a Windows form application, the app.config file is automatically read, and if you use a web form then the web.config file is used. Now think about it, if we calling an Enterprise Library Component from a pipeline component, neither the app.config or web.config is going to be called, because this is excuted in the App Domain for the BizTalk process, we will need to configure the config file to use the ‘BTSNTSvc.exe.config’, if you ar efamilair with BizTalk, this is the place that BizTalk server reads for configuration as well as custom configuration. This file is located in C:\Program Files\Microsoft BizTalk Server 2006 by default. You can add many things here for example a custom timeout for HTTP connections:

     

    </system.runtime.remoting>

    <system.net>

    <connectionManagement>

    <add address="*" maxconnection="5000"/>

    </connectionManagement>

    </system.net>

     

    </configuration> 

    So, what we going to do is create a new logging application configuration file for Enterprise Library to read, then, we will modify the BTSNTSvc.exe.config to add a reference to the configuration file. So that at runtime the configuration file can still be found. There are many ways to do this, you could even use the SSO database, but for this article I am sticking to simple configuration files. We will store these configuration files in the C:\Program Files (x86)\Microsoft BizTalk Server 2006 folder, excuse my path, I am on a 64 bit OS.

  • Open the Enterprise Library Configuration tool, located at Start\Program Files\Microsoft patterns & practices\ Enterprise Library 3.1 – May 2007 \Enterprise Library Configuration.
  • Open the ‘BTSNTSvc.exe.config’ by clicking File > New Application
  • Right click on the Application Configuration name and add a new Logging Application Block by clicking the file name and select New > Logging Application Block.

  • Select the Trace Listeners and right click on it to select the New > Rolling File Trace Listener.

  • Select Formatter on the right hand pane and select Text Formatter

I like to put all my log files in %windir%\system32\logfiles\<application name>\filename<TimeStampPattern>.log, since many MS application do this, why not make our application do the same to keep log files centrally located. We going to implement a rolling flat file logger that increments

  • Change the FileName of the log file to %windir%\system32\logfiles\BizTalk\Pipeline.log (NOTE: DO NOT USE %WINDIR% use the path C:\…. etc, else EL will append the current execution folder to %windir%)
  • Change the attribute for the RoleFileExistsBehavior to Increment
  • Change the RoleInterval to Day, this will create a new log file per day, similar to IIS
  • Change the TraceOutputOptions to DateTime, so we can get a nice row prefix for the logging

The options set here can be overridden when you hook the listener to a Special Source, which we see later.

This is what my configuration looks like:

 

  • The next stage is to assign the listener. To do so you select Formatted EventLog TraceListener from the Special Sources.
  • On the drop down many assign it the Rolling Flat File Trace Listener

So what we have done is created a listener and then told the configuration to log errors and warnings to this listener. If you click the plus sign you can override the default settings we defined earlier on.

  • Set the Rolling Flat File Trace Listener in the Category Sources\General\Formatted EventLog TraceListener. Select the node and select the Referenced TraceListener to Rolling Flat File Trace Listener from the dropdown.

 

From a configuration perspective we are complete, we configured the Rolling Flat File as the location for logging.

 

We hooked the listener to be called when Logging Errors and Warnings and when the category is General.

The configuration tool from Enterprise Library is extremely customizable, for example we could add a new listener for the event log and create a new category called "Critical" and then hook the event log listener to this category, so that if you call the logger, with a different category, it will log to a different source, based on the configuration. i.e.

Logger.Write(message, category);

 

What is left is that we need to save the configuration to file, in my case, I will save it to:

C:\Program Files\Microsoft BizTalk Server 2006\ MMIT.BizTalk.Components.Logging.config

What we now need to do is add a section to the BTSNTSvc.exe.config that points to the configuration file we created.

  • Open the BTSNTSvc.exe.config file

Be careful adding custom conifgSection to BTSNTSvc.exe.config file: it must be the first child of the root element.

You will get an unfriendly message in the event log:

Event Type:    Error

Event Source:    BizTalk Server 2006

Event Category:    BizTalk Server 2006

Event ID:    5410

Date:        6/2/2008

Time:        7:35:17 PM

User:        N/A

Computer:    V-BIZDEV32I-02

Description:

A failure occurred when executing a Windows service request.

 

Service request: Start

 

BizTalk host name: BizTalkServerApplication

Windows service name: BTSSvc$BizTalkServerApplication

 

Additional error information:

Error code: 0xc0c0153a

Error source: BizTalk Server 2006

Error description: A BizTalk subservice has failed while executing a service request.

 

Subservice: Tracking

Service request: Start

 

Additional error information:

Error code: 0x80131534

Error source: Microsoft.BizTalk.Bam.EventBus

Error description: The type initializer for ‘System.Data.SqlClient.SqlConnection’ threw an exception.

 

For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.

 

  • Add the following section to the config file

<?xml version="1.0" ?>

<configuration>

<configSections>

<section name="enterpriseLibrary.ConfigurationSource" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationSourceSection, Microsoft.Practices.EnterpriseLibrary.Common, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />

</configSections>

<enterpriseLibrary.ConfigurationSource selectedSource="File Configuration Source: MMIT.BizTalk.Components.Logging.config">

<sources>

<add name="File Configuration Source: MMIT.BizTalk.Components.Logging.config" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" filePath="C:\Program Files\Microsoft BizTalk Server 2006\MMIT.BizTalk.Components.Logging.config" />

</sources>

</enterpriseLibrary.ConfigurationSource>

 

  • So the entire configuration file for the BTSNTSvc.exe.config looks like this (assuming you don’t have any other custom stuff in it, you might do!)

<?xml version="1.0" ?>

<configuration>

<configSections>

<section name="enterpriseLibrary.ConfigurationSource" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationSourceSection, Microsoft.Practices.EnterpriseLibrary.Common, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />

</configSections>

<appSettings>

<add key="StagingDataManagementWS" value="http://localhost/Workflow/StagingGateway/StagingDataManagementWS.asmx"/&gt;

</appSettings>

<enterpriseLibrary.ConfigurationSource selectedSource="File Configuration Source: MMIT.BizTalk.Components.Logging.config">

<sources>

<add name="File Configuration Source: MMIT.BizTalk.Components.Logging.config" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" filePath="C:\Program Files\Microsoft BizTalk Server 2006\MMIT.BizTalk.Components.Logging.config" />

</sources>

</enterpriseLibrary.ConfigurationSource>

 

<runtime>

<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">

<probing privatePath="BizTalk Assemblies;Developer Tools;Tracking;Tracking\interop" />

</assemblyBinding>

</runtime>

 

<system.runtime.remoting>

<channelSinkProviders>

<serverProviders>

<provider id="sspi" type="Microsoft.BizTalk.XLANGs.BTXEngine.SecurityServerChannelSinkProvider,Microsoft.XLANGs.BizTalk.Engine" securityPackage="ntlm" authenticationLevel="packetPrivacy" />

</serverProviders>

</channelSinkProviders>

 

<application>

<channels>

<channel ref="tcp" port="0" name="">

<serverProviders>

<provider ref="sspi" />

<formatter ref="binary" typeFilterLevel="Full"/>

</serverProviders>

</channel>

</channels>

</application>

</system.runtime.remoting>

<system.net>

<connectionManagement>

<add address="*" maxconnection="5000"/>

</connectionManagement>

</system.net>

</configuration>

Notice I have PublicKeyToken in the reference here above, so that it forces to look in the GAC!

The option in read is other customizing not needed here, but put in for additional info.

 

So after making these configuration files, you can quickly review them to have a look, I sorted my BizTalk folder my date modified to get easy access to them.

 

I now add some log calls in my custom pipeline component, so I open my disassemble component and add some logging e.g.

 

This particular disassemble component is called by a custom pipeline, in a separate BizTalk project, you will notice that my component project is just standard c# project, so the Pipeline will look in the GAC for the custom component, here it is:

So I hope this brings back a memory, the Pipeline is executed in a Receive Location like this:

I now drag my component DLL to the GAC, restart BizTalk services etc and the pipeline will now execute with the updated component J

 

Now, what I do is compile my custom pipeline component and deploy the component to the GAC, and restart the BizTalk application and Host Instance that uses this custom Pipeline component, here is a picture of my pipeline that calls this custom component. You do not need to recompile BizTalk projects, just the dll for the pipeline component!

 

I can now set breakpoints in the custom pipeline component, so that when the pipeline executes it will hit the breakpoint, what you do is attached to the BTSNTSvc.exe services, Im too lazy to find out which one here below, you may have other host instances running:

 

NOTE: Make sure you attach to Biztalk After you deployed the dll to the GAC and then restarted the host instances in that order (Only instances using the pipeline, in my case only one service to restart)

If you BizTalk service cannot restart you probably got an error in the BTSNTSvc.exe.config

 

To see if my logger works (You can create a test project for this, but then your configuration will need to be in an app.config file, we will do this later, since I like test driven development.

So now, we drop a file in the receive location that is configured to run the pipeline.

 

Above is the file receive location, with the custom pipeline.

 

Ok, I now drop a file at the receive location and then it hits the break point.

 

I get an error!

 

What you need to do here is ensure this assembly is in the GAC

  • Microsoft.Practices.EnterpriseLibrary.Logging.dll

So drag the dll into the GAC or use your tool GACUTIL and then RESTART the host instance, since it is on host start up that the Microsoft.Practices.EnterpriseLibrary.Logging.dll will be loaded in memory and cached

After doing this, my step into works

 

However, I now get a new error:

The inner exception has this:

 

So we need to add this to the GAC to:

 

Ok, restart instance, attached to process and off we go again, fun debugging pipelines!

To cut a long story short, you can debug the problems with Enterprise Library and figure out the problem, in all these assemblies need to be in the GAC:

  • Microsoft.Practices.ObjectBuilder.dll
  • Microsoft.Practices.EnterpriseLibrary.Logging.dll
  • Microsoft.Practices.EnterpriseLibrary.Common.dll

But before we get ahead of ourselves, I get another exception.

If you get this, ensure the BizTalk account has permission to the folder and create the folder BizTalk at the location of your log file or whatever you chose to use!

Now I get my log file!

 

And if we open it:

—————————————-

Timestamp: 6/2/2008 6:44:28 PM

Message: Started File Import:

Category: General

Priority: -1

EventId: 1

Severity: Information

Title:

Machine: V-BIZDEV32I-02

Application Domain: DefaultDomain

Process Id: 5340

Process Name: C:\Program Files\Microsoft BizTalk Server 2006\BTSNTSvc.exe

Win32 Thread Id: 4676

Thread Name:

Extended Properties:

—————————————-

—————————————-

Timestamp: 6/2/2008 6:44:28 PM

Message: Started File Import: D:\Data\Feeds\POST_SPS\GMUK\VXUK\CAPGEMINI\OSC\TESTIGNORE.txt

Category: General

Priority: -1

EventId: 1

Severity: Information

Title:

Machine: V-BIZDEV32I-02

Application Domain: DefaultDomain

Process Id: 5340

Process Name: C:\Program Files\Microsoft BizTalk Server 2006\BTSNTSvc.exe

Win32 Thread Id: 4676

Thread Name:

Extended Properties:

—————————————-

 

That’s it really, so you can add logging calls to your program and can even create other logging categories instead of general etc, so above I might as well add the file import end log and call it again when the file import is complete, totally up to you!

There is one problem left, you notice that a timestamp was not created and appended to the file!!!

However, I waited an entire day (just kidding, changed the time on the computer on my DEV machine) and get this when I dropped another file in the receive location:

 

Ok, that’s it for now. Don’t forget to add the other assemblies to the referenced assemblies, so when you have them in source safe, you remember to deploy them to the GAC!

  • Microsoft.Practices.ObjectBuilder.dll
  • Microsoft.Practices.EnterpriseLibrary.Logging.dll
  • Microsoft.Practices.EnterpriseLibrary.Common.dll

 

 

In later blogs we will have a look at how we can leverage caching to optimize BizTalk custom assemblies.

Advertisements
Uncategorized

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s