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”);
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;
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: BizTalk