BizTalk Application Tracing, Part II

In my last post I showed how to add conditional tracing to your BizTalk application using a flag stored in an external configuration file. While this is the easiest “lookup” solution to set up, it also has a few downsides. Namely, being forced to restart the host instance to absorb changes and the requirement to keep configuration file(s) in sync across servers.

So how about using the Business Rules Engine (BRE)? Now I’ve seen discussion saying that this isn’t a great way to go. Mainly because the BRE isn’t set up to be a metadata repository and its strength lies in calculating complex rule sets, not doing simple lookups. Also, folks may complain that they have to create an XML document or .NET class to use as an input “fact.” All valid complaints, but, I wanted to see if I could build something that was very low maintenance and still high performing. For me, the BRE provides the cache refresh capability I want, and the central management feature that’s key to maintainability.

So instead of creating some custom fact type (XML doc, class, etc), I decided to use a standard .NET type as an input. You can’t just use a “string”, as it’s viable for the rule “condition” but can’t be used for the “action.” So, I used the StringBuilder class found in the mscorlib assembly. You’ll see here, that I’ve built a rule policy with four versions. I have a versions to turn OFF tracing, turn ALL tracing on, and to turn tracing on for just pipelines or orchestrations. See that the rule “action” just adds text to the StringBuilder fact. So NO custom facts needed, just standard .NET built-in types.

I also set up a Vocabulary that allows me to use a drop-down list of possible tracing flags.

Now I can promote and demote (actually deploy and undeploy) trace flag settings without modifying code or updating files. I can be confident that the policy cache will be refreshed (60 seconds by default) without restarting any processes. Within my orchestration, now my “trace block” looks like this …

I have an orchestration variable of type StringBuilder and pass that into my rule policy. My decision condition then checks the value of “traceFlag.ToString()” which equals the value designated in the deployed rule version. If you remember from Part Iof this saga, I also created a pipeline component that used the configuration file trace flag. Now, let’s update this component to use the BRE instead. After adding a project reference to Microsoft.RulesEngine.dll, I updated my pipeline component’s “Execute” method to look like this …


public IBaseMessage Execute(IPipelineContext pc, IBaseMessage inmsg)
{
//create StringBuilder to pass into ruleset
StringBuilder sb = new StringBuilder();
Policy p = new Policy(“Blog.BizTalk.Tracing.Flag”);
p.Execute(sb);

if (sb.ToString() == “ALL” || sb.ToString() == “Pipeline”)
{
Stream s = inmsg.BodyPart.GetOriginalDataStream();
byte[] buffer = new byte[s.Length];
s.Read(buffer, 0, Convert.ToInt32(s.Length));
string output = System.Text.UTF8Encoding.UTF8.GetString(buffer);

System.Diagnostics.Debug.WriteLine(“Pipeline Trace: Body is ” + output);
}
p = null;
sb = null;

return inmsg;

 

So you can see, very little code to call the rule and check the value. Create a StringBuilder, create the Policy object, and execute the rule set. Now, from a performance standpoint, calling into the BRE should have a negligible impact. Once you call a rule policy the first time, it’s cached in memory for future requests. So, while I haven’t run the numbers on this, I can’t imagine doing such a simple rule call would have any noticeable effect on pipeline performance.

To test this, I processed my orchestration, first with the “Pipeline” trace deployed, then with the “Orchestration” trace deployed, and finally with the “None” scenario deployed. You can see the result in the log here …

So, over these two posts you’ve seen how to trace using a configuration file and the BRE. You could also potentially use the SSO API (assuming you also implemented a caching algorithm), but at this very moment, I’m a fan of using the BRE. Any other favorite methods you have?

Technorati Tags:



Categories: BizTalk

6 replies

  1. Nice one Richard – great idea about the stringbuilder. I wonder if you could simply use a String?? with System.String….. methods?

    Gives a great alternative to app.Config settings

    Take care,

    Mick.

  2. I tried that (using a “string”), and while it seems fine for the “condition” of the rule, you aren’t allowed to drag the “System.String” object to the “action” section.

  3. Alright Richard, now that it’s been a while since you made the post, how often have you actually used this? Although the ability to turn off tracing is something I’d love to have, I think it behooves Microsoft to provide a better way to shut this off. Reading the blog it seemed like a little too much overhead since only a few special persons can see the output in the first place.

    I don’t mean to be overly pessimistic, but thought I’d share my two cents.

  4. Hey Victor, I have actually used this on one deployed project. In the caes of exception tracing, there was a lot of information I wanted to see in the Event Log, but during regular processing, it would be excessive to discharge so much information to the Log. Agreed that it can be a lot of setup for a fringe scenario, but until you can have more aspect-oriented tracing that sits lightly atop the code, I think you’d be stuck with these sorts of solutions.

    Other thoughts on how you’d do this?

  5. Hi Richard,

    Instead of having rule and publishing multiple version, what about having a vocublary. you just need a helper method to access the value and .net helper method can access the vocubalries which are not even published

    eg:
    Vocabularies
    TraceAll = true
    TraceOrchestration = false
    TracePipeline = true

    Helper Method :

    public static void GetVocabularyConstantValue(string vocabularyName, string constantName,
    ref string constantValue, ref string constantType)
    {
    IList vocabs = GetVocabularies(vocabularyName, string.Empty);
    foreach (Vocabulary vocab in vocabs)
    {
    Hashtable definitions = new Hashtable(vocab.Definitions.Count);
    definitions = (Hashtable)vocab.Definitions.SyncRoot;
    if (definitions.ContainsKey(constantName))
    {
    LiteralDefinition literalDef = (LiteralDefinition)definitions[constantName];
    constantType = literalDef.Value.GetType().ToString();
    constantValue = literalDef.Value.ToString();
    break;
    }
    }
    }

    Sample :

    GetVocabularyConstantValue(“TraceOrchestration”, “TraceOrchestration”,constantValue, constantType)

    if (constantValue)
    Trace.WriteLine (“I can trace ..”);

    Regards,
    Prasanna

Trackbacks

  1. BizTalk Application Tracing, Part I « Richard Seroter’s Architecture Musings

Leave a Reply

Fill in your details below or click an icon to log in:

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

%d bloggers like this: