a trace of thought on...BizTalk Server, Team Foundation Server, Windows Mobile, etc. RSS 2.0
 Thursday, December 14, 2006

Have you ever wanted to get real-time metrics on:  How many times has a particular orchestration executed on this node in the BizTalk group?  What does the average execution time for my pipeline component looking like?  How many instances of a particular orchestration are currently executing across the group, not including dehydrated instances?

Questions like this can be tough to answer - the built-in BizTalk counters are too coarse-grained, and Tracking & BAM are only partially useful here (particularly if you want high frequency samples.)  What you would like is the ability to get fine-grained "request metrics" on all of your BizTalk orchestrations and pipelines in a way that is simple to implement and easy to consume.

I've been leading an open source project called QuickCounters for quite some time now - though we've just recently moved into CodePlex.  It is a library that will be of interest to BizTalk developers - but it can be used in much broader settings.  I had a chance to present on this topic at the Twin Cities .NET Users Group (on 11/2/2006 - presentation here.)

QuickCounters is a .NET library which makes it extremely easy to implement the common, request-level performance counters that are interesting in just about any service you might write.  You can use this library to instrument  general .Net components, web services, BizTalk orchestrations, pipeline components, remoting interfaces, enterprise service components...you get the idea.  There is special support in the library for BizTalk and WCF scenarios, but it is quite easy to use in any case.

QuickCounters recognizes that the Windows Performance Counter technology that has been with us for some time is often still the best choice for providing (and consuming) detailed performance metrics.  QuickCounters also recognizes that for any given service request there are several metrics which turn out to be interesting for performance testing, operational health analysis, and historical trending. The idea with QuickCounters is to raise the level of abstraction from that of an individual performance counter up to the request itself, using a simple API.

Suppose you want to gather these metrics for each type of request in your system:

  • Requests Started
  • Requests Executing
  • Requests Completed
  • Requests Failed
  • Request Execution Time
  • Requests/Hour
  • Requests/Min
  • Requests/Sec

Although the .NET performance classes would give you a good start, it will still be a chunk of work.  With QuickCounters, you describe your requests in a simple xml format, and include a simple code snippet in each request implementation:

void SampleRequest()
{
   RequestType someRequest = RequestType.Attach("MyApplication","someRequest");
   someRequest.BeginRequest();

   try
   {
      // Do useful work...
      someRequest.SetComplete();
   }
   catch
   {
      someRequest.SetAbort();
      throw;
   }
}
        

After a quick "install" of the xml that describes your requests (via the included "QuickCounter viewer" utility) you are on your way.  You can see all eight metrics described above for all of your requests (which each become a Performance object) - in PerfMon, with MOM, or any other performance counter consumer. 

For a BizTalk orchestration, you will simply have a variable of type RequestType, which you will assign in an expression shape at the top of your orchestration via the static "RequestType.Attach" method, followed by a call to BeginRequest: 

quickCounterDemo = QuickCounters.RequestType.Attach(
    "QuickCounterDemo","demo",
    QuickCounterDemo(Microsoft.XLANGs.BaseTypes.InstanceId)); 
quickCounterDemo.BeginRequest();           

Successful completion should end with another expression shape that calls SetComplete, otherwise SetAbort.  (Full sample referenced below.)  And yes, the library understands that an orchestration's execution will often begin on one node in your BizTalk group and continue/complete on a different node. 

Of course, if you have many requests, and many nodes in your BizTalk group, it can be a hassle to add everything to PerfMon.  20 requests * 3 servers = 60 interactions with PerfMon's UI.  You might remember to save an .msc file, but you might not.  Here is where the QuickCounter viewer comes into play.  Since you've already written an xml file that describes your requests, just let the viewer know about that file -  and a comma separated list of servers you are running on:


(click)

(The viewer has benefitted substantially from John Thom's contributions...)

Now, the WCF support in the library is...amazing, and completely the result of contributions from Tomas Restrepo.  Keep an eye on his blog for a full discussion, but the bottom line is that creation of the simple xml format and all API calls (BeginRequest/SetComplete/SetAbort) are handled for you automatically simply by applying an attribute (or a behavior - your choice) to your WCF service implementation.  How cool is that?

Our CodePlex home is here.  Downloads and source code here.  Contributors here.

I expect we'll release about once a month or so for awhile - give it a spin and let us know what you think.  It is being used by some very large BizTalk projects (in production) with good success right now.

Thursday, December 14, 2006 4:53:19 PM (Central Standard Time, UTC-06:00)  #    Comments [0] -
BizTalk Tools
 Wednesday, November 29, 2006

There are two interesting BizTalk 2006 bugs to be aware of - it seems like they would be encountered fairly often, so I'm a little surprised that I haven't seen more newsgroup/forum activity around these.

The first bug is encountered when you attempt to start a BizTalk 2006 application definition with orchestrations that have been bound to different hosts.  (Say, OrchA in HostA, and OrchB in HostB.)  After the application has been deployed, the first time the application is started (and 'orchestration start/enlist' is included in the start options) you will receive an error that looks something like this:

Microsoft.BizTalk.ExplorerOM.BtsException: Could not enlist orchestration 'BizTalkSample.Orchestrations.Echo,BizTalkSample.Orchestrations, Version=1.0.0.0, Culture=neutral, PublicKeyToken=05a4a8d4071035d9'. Could not enlist orchestration 'BizTalkSample.Orchestrations.Echo,BizTalkSample.Orchestrations, Version=1.0.0.0, Culture=neutral, PublicKeyToken=05a4a8d4071035d9'. Value does not fall within the expected range.

You can work around this error by manually starting your orchestrations in the MMC, either one-at-a-time or grouped by host.  The error only occurs the first time you attempt to start - all future attempts will succeed.  This is because the underlying bug has to do with the creation of subscriptions for the orchestrations. 

This is actually a regression from BizTalk 2004 - where you could in fact change multiple orchestrations (across differing hosts) to a started state via the BtsOrchestration 'Explorer OM' class in a single transaction (i.e. before calling SaveChanges.)  In addition to the behavior just described with BizTalk 2006, you can't do this kind of Explorer OM work once multiple hosts are involved in BizTalk 2006.

But hey, there is a hotfix.  Contact PSS and ask about KB927052.

The second bug is encountered when you have a BizTalk 2006 application with multiple MSMQ receive locations.  You will find that restarting your host instances takes an excessively long period of time.  This is due to a bug in the adapter which was not allowing the host service to stop correctly (the Service Control Manager would eventually just terminate the service...)  Contact PSS and ask about KB928222.

Wednesday, November 29, 2006 10:13:24 AM (Central Standard Time, UTC-06:00)  #    Comments [0] -
BizTalk Insights
 Wednesday, October 11, 2006

Update: The tracking query as a TRQ file is available here, per a comment on this post.

I just got back from a week at the "Microsoft SOA & Business Process" conference in Redmond.  Lots of discussion on BizTalk 2006 R2, the new .NET Adapter Framework, Windows Communication Foundation (WCF), Windows Workflow (WF), Microsoft Office Sharepoint Server 2007 (MOSS).  Great stuff.

I did a session at the conference on Friday titled "Applying Maximum Sustainable Throughput to a Management/Operations Strategy".  (OK, the title may have scared a few people off...) The content was an extension of what I presented to the Twin Cities BizTalk User Group in September.  The overall theme was relating what you learn during your performance testing phase to your operations strategy, and ensuring that you have application-level metrics that represent operational boundaries you would like to "live within".  In particular, I discussed how to formulate your performance goals, how to measure against them as operational parameters, and how to proactively monitor with a tool such as Microsoft Operations Manager (MOM).  We went on to discuss how to choose the workloads (e.g. send, receive, or orchestration work) for new servers that you place in your BizTalk group, depending on what you see within various BizTalk work queues and throttling states.  I've put the slides for the session here for your perusal. 

One of the demos showed a HAT query I've worked up which will report on how many times each orchestration has run within a given time window, along with the percent of total transaction volume it represents, time duration, and activity rates (per second, per minute, and per hour). You can put the following query in a .TRQ file (like OrchestrationDurationsAndRates.trq) and the put it within C:\Program Files\Microsoft BizTalk Server 2006\Tracking\Queries (or the equivalent on your server.) It will then appear within the "Queries" menu in HAT. This can be a genuinely useful query to have at your disposal, both during performance testing and in production.  You can run this in Query Analyzer if you prefer - just uncomment the lines that define UtcOffsetMin.  Note that rate calculations are dividing across the entire time window, which assumes a fairly steady traffic pattern.

If you're trying to determine compliance within an SLA such as "95% of all requests must be satisfied within 15 seconds or less", you might add an item to the select clause below along the lines of "average(service duration) + (2*stddev(service duration))", if the distribution of your transaction durations tends to be normal (per your high school stats class.)

declare @beginTime as datetime
declare @endTime as datetime

declare @TotalCountInWindow as int

--
--  SET THE TIME WINDOW FOR YOUR QUERY HERE
--
select @beginTime =DateAdd(hour, -2, GetDate())
select @endTime = GetDate()

-- Only need to uncomment this select when inside of query analyzer,
-- where UtcOffsetMin won't be defined.
-- declare @UtcOffsetMin as int
-- select @UtcOffsetMin = 
-- -1*DateDiff("mi",CONVERT(varchar,GetDate(),0),CONVERT(varchar,GetUTCDate(),0))

select @beginTime = dateadd(minute,-1*@UtcOffsetMin,@beginTime)
select @endTime = dateadd(minute,-1*@UtcOffsetMin,@endTime)

SELECT @TotalCountInWindow = count(*)
FROM dbo.dtav_ServiceFacts sf WITH (READPAST)
where [ServiceInstance/StartTime] between
@beginTime and @endTime
and [ServiceInstance/State] = 'Completed'
and [Service/Type] = 'Orchestration'


SELECT 
[Service/Name],
count(*) as TotalCount,
(cast(count(*) as float)/cast(@TotalCountInWindow as float))*100 as PercentOfTotal,
avg([ServiceInstance/Duration]/1000.0) as AverageDuration,
min([ServiceInstance/Duration]/1000.0) as MinDuration,
max([ServiceInstance/Duration]/1000.0) as MaxDuration,
stdev([ServiceInstance/Duration]/1000.0) as StdDevDuration,
count(*)/DateDiff("hh",@beginTime,@endTime) as perHour,
count(*)/DateDiff("mi",@beginTime,@endTime) as perMinute,
cast(count(*) as float)/DateDiff("ss",@beginTime,@endTime) as perSecond

FROM dbo.dtav_ServiceFacts sf WITH (READPAST)
where [ServiceInstance/StartTime] between
@beginTime and @endTime
--and  [ServiceInstance/Duration] > 0
and [ServiceInstance/State] = 'Completed'
and [Service/Type] = 'Orchestration'
group by [Service/Name]


Got your own favorite HAT query? Post it in the comments - maybe we'll start a new section for them. Some shops deploy their custom HAT queries directly with their BizTalk applications...For Deployment Framework folks, that looks as follows (assuming a project subdirectory called DeployedHATQueries):

	
<target name="deployHatQueries">
  <copy todir="${btsDir}\Tracking\Queries" overwrite="true">
      <fileset basedir="DeployedHATQueries">
         <include name="**\*.trq" />
      </fileset>
  </copy>
</target>
Wednesday, October 11, 2006 7:34:25 AM (Central Standard Time, UTC-06:00)  #    Comments [3] -
BizTalk Insights
 Tuesday, September 19, 2006

Late notice (again) but if you can…be sure to join us at 6:00 pm on Thursday, September 21st at the local Microsoft office in Bloomington.  You can register here.

Scott Colestock (me) will be presenting this month on the topic of relating what you learn during performance testing of a BizTalk application to your operations/monitoring strategy.  Should be good fun (really!) and of course we’ll have the usual food and beverages.

Tuesday, September 19, 2006 1:29:51 PM (Central Standard Time, UTC-06:00)  #    Comments [0] -
General
 Tuesday, September 12, 2006

Despite all the functional testing and stress testing you do prior to releasing your BizTalk app into production, unexpected behavior can (and often will) happen just the same.  Production usage just winds up introducing all sorts of permutations (including interactions with external systems) that are hard to predict earlier in the lifecycle.

The goal, of course, is to minimize the the operational "care and feeding" that an application requires over time.  Making this happen is mostly a function of using the application's "diagnostic surface area" (logs, counters, MOM packs, etc.) to feed back into each release cycle.  But we also need post-mortem tools when the host environment terminates unexpectedly or stops responding (whether that environment is BizTalk, IIS, COM+, Sql SSIS, etc.)

While a well-designed app will be able to successfully restart and resume processing (with full data integrity) at such a point (i.e. after the host has been terminated), there is still operational expense that has been injected.  We want to find and eliminate these problems...

Using the Visual Studio debugger is almost never an option in production, of course.  We need the ability to capture the current state as a "dump file" and do offline analysis. 

The "Windows Debugging Tools" are designed for this purpose (and you will often use these during a call with Microsoft's support staff, so it is good to be familiar with them.)  The debugging tools are a pretty large subject - so here, we are just going to cover the bare minimum required to capture a dump file for your running BizTalk process when it appears to be hung with a large number of "Active" service instances.

Step By Step:

  • Install or xcopy the Windows Debugging Tools to the server where BizTalk is currently hung (or crashing unexpectedly.)  It can be helpful to install in an easy location for command line access like 'c:\debuggers'.
  • From command line, run the following from the command line to get process IDs for all BizTalk hosts:
    typeperf "\BizTalk:Messaging(*)\ID Process" -sc 1
  • Run 'adplus.vbs' in crash or hang mode, depending on whether the process ends unexpectedly (crash) or has become unresponsive (hang).  To generate a hang dump, your command line might look like:
    c:\debuggers\cscript adplus.vbs –hang –CTCF –p (pid from last step) –o c:\temp
  • Copy the dump file to an offline location if need be.
  • Set an envrionment variable called '_NT_SYMBOL_PATH' to 'srv*c:\symbols*http://msdl.microsoft.com/download/symbols'.  Alternatively, launch WinDbg.exe from the debuggers directory and use the File-'Symbol File Path' menu.  This will ensure that you are automatically downloading the correct symbols when you analyze the crash dump.  
  • Start WinDbg.exe, and use File-'Open Crash Dump' to open your dump file.  Then, in the command window, use:
    '.load C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\sos.dll' to load managed code debugging extensions.
  • In the command window, use !EEStack to get a full stack trace.  Use Edit-Find to search for your custom code method name or the name of your orchestration.  Look for patterns that indicate the cause of the hang ("hmmm, all my threads seem to be inside Thread.Sleep. That's funny.")  Use !help from the command window to begin learning about the rest of SOS (to assist with diagnosing managed memory leaks, etc.)

For more information on the Windows debugging tools, see here.

Tuesday, September 12, 2006 7:30:57 AM (Central Standard Time, UTC-06:00)  #    Comments [0] -
BizTalk Insights
 Tuesday, August 15, 2006

Tired of havng incredibly long xpath statements when using the "xpath" keyword in your orchestration expression shapes?  (They are generally long because of the xml namespace issues, unless your documents do not use namespaces.  When namespaces are in play, "local-name()" tends to overwhelm your actual path content.)

For BizTalk 2006, we can take advantage of the fact that System.Xml 2.0 added the ability for documents to supply namespace mappings themselves when doing xpath work - without the need for manually populating and using a XmlNamespaceManager instance, as was the case for .Net 1.x.  Note that XPathNavigator now (as of .net 2.0) has a SelectSingleNode method which can accept an implementation of the new IXmlNamespaceManager interface (which XPathNavigator itself implements.) This means that the 'xmlns:someprefix=someuri' declarations in your instance document can actually be used automatically, such that your xpaths can use the same prefixes when issuing a select. .Net 1.x had no such mechanism.

So, in whatever "utility" class you have sitting around to help you out when doing orchestration work, add the following static method.  (I generally put such things outside of a namespace - that way they are a bit more concise inside the orchestration expression editor.) In high-performance scenarios, may want to measure the performance of this approach vs. the built-in xpath keyword.  Recall that messages can be passed as XmlDocument instances, so your expression window might have: myString = XmlUtility.GetXPathStringResult(myMessage,"/spf:someparent/spf:somechild");

public static string GetXPathStringResult(
    XmlDocument document,
    string xpath)
{
    XPathNavigator nav = document.CreateNavigator();

    // (so namespace mappings are in scope when we select)
    nav.MoveToChild(XPathNodeType.Element); 

    XPathNavigator node = nav.SelectSingleNode(xpath, nav);

    return node.Value;
}    
    
Tuesday, August 15, 2006 9:58:24 AM (Central Standard Time, UTC-06:00)  #    Comments [1] -
BizTalk Insights
 Friday, June 30, 2006

(Update: The original download files were missing the PDB-to-GAC functionality I've discussed before.  Please download again if you have already...)

The BizTalk Deployment Framework has been updated to work with BizTalk 2006...It is hard to believe that this project has been going on since May of 2004!

The Deployment Framework for BizTalk 2006 still has the same goals as the 2004 version:

  • Streamline the deployment process for developers, ensuring repeatability
  • Make it easier for a team of BizTalk developers to stay in sync - not just with BizTalk artifacts, but with all the other infrastructure that surrounds the solution (virtual directories, queues, file folders, etc.)
  • Extremely close parity between server-side deployments and developer deployments - so you are always testing your server deployments as you go through a typical developer work day.

BizTalk 2006 itself introduced quite a few features to make deployment easier, and can work fine for small (or solo) projects.  Here are a few limitations I've encountered:

  • Though much improved, it is still possible to get into "dependency chaos" - where you spend time manually undeploying/deploying individual artifacts.
  • Binding changes have to be communicated "manually" between developers on a team, since the import process is done through the Admin MMC or command-line.  Just "getting latest" from version control isn't sufficient.
  • Binding files for your various environments have to be maintained as separate files (manually), rather than "merging in" environment-specific settings
  • Artifacts such as rules, virtual directories, queues, folders, additional dependent assemblies, etc. can be represented as "Resources" within the Admin MMC (and in exported MSIs), but not in a fashion that easily moves between developers on a team.

So!  To get started with this version, download the Deployment Framework (Tools) zip and run the MakeBizTalkExternalTools_VS2005.vbs script.  This will add entries to the Visual Studio tools menu for deploying and undeploying using the framework.  You can download the full sample to see the framework in action (first build it, then do Tools-BizTalk Deploy.  You'll see something like this.)

The high-level approach is the same as the 2004 framework - you supply a small project-specific NAnt script that indicates via properties what elements of a deployment your solution requires.  You include BizTalkDeploymentInclude.nant to get all the core deployment functionality, and make sure the DeployTools directory is copied to your project.  (Unzipping the Deployment Framework Core into your project is a good way to do this.)  See the documentation for a more complete discussion.

The primary difference in the upgraded framework for BizTalk 2006 is that we now create a BizTalk Application definition, and use BTSTask to add all BizTalk artifacts as resources within that application.  Starting and stopping the application is done at an application level rather than per port/per orchestration.

Packaging up your solution as an MSI can be done with the WiX-based scripts that have been in the framework for awhile, or by using the MSI export mechanism in BizTalk 2006, if you prefer.  (The latter solution will require a few additional steps, and doesn't give you the parity described earlier.  But it works if you need to go that route.)

Other Notes:

  • NAnt .85 RC4 (and NAntContrib ) is required.  Be sure to copy the new BizTalk.NAnt.Tasks.dll to NAnt's bin directory.  We need to call BizTalk's .net 2.0 assemblies, and NAnt wasn't built against 2.0 -- so change nant.exe.config to have only<supportedRuntime version="v2.0.50727" /> in the<startup> element.
  • Log4net usage in the sample (which isn't required of course for the framework) has been updated to log4net 1.2.10 , as has my serializable wrapper.  You can find the new log4net.Ext.Serializable in the Tools download (which is useful all by itself, apart from the framework.)
  • You can actually use the BizTalkDeploymentInclude.nant file in this release with BizTalk 2004, if you like, to aid in your migration.  There is NAnt property to indicate 2004 vs. 2006.
  • Scan all the previous release notes...

Leave comments with any questions/issues/etc.  Enjoy!

Download: Full Sample, Framework Core, Tools Source , Docs

Friday, June 30, 2006 2:46:41 PM (Central Standard Time, UTC-06:00)  #    Comments [23] -
Deployment Framework
 Tuesday, June 27, 2006

Update: Andy pointed out that Tom Abraham has given this a thorough treatment here.

There appear to be cases where having BizTalk 2004 and the .NET 2.0 framework installed on the same machine may cause you some difficulty.  I've seen a few instances where the BizTalk service will not start...or where the BizTalk 2004 process is loading (gulp) the 2.0 runtime (so says Process Explorer.)  This latter behavior will result in the VS2003 debugger not attaching correctly (among other things...)  See this kb.

To fix this, you can modify the BTSNTSvc.exe.config file to include the following (after 'configSections'):          

<startup>
<supportedRuntime version="v1.1.4322"/>
</startup>
Tuesday, June 27, 2006 9:45:36 AM (Central Standard Time, UTC-06:00)  #    Comments [1] -
BizTalk Insights
 Friday, June 23, 2006

In my last post I indicated there was a better story in BizTalk 2006 for working with the C# code that is generated as an intermediate when compiling ODX (orchestration) files - that is, better than having to deal with temporary files and the BizTalk 2004 File Dump utility.  I

If you've worked with BizTalk 2006, you might have already stumbled across this.  The xlang compiler for BizTalk 2006 is kind enough to place the intermediate C# file for your ODX directly in the project directory.  If you have multiple orchestrations in an assembly, you will find a C# file for each orchestration - but only one of those files will actually have content (all the generated C# code is consolidated into one file.)

What this means is that you can do symblic debugging of orchestrations in a fashion far easier than what I described for BizTalk 2004.  The Edit/Debug cycle might look like this:

  1. Build your orchestration project.
  2. Open the associated (generated) C# file - perhaps make it a solution item for convenience.
  3. Search for something in one of your expression shapes (say "MyClass.Execute"), and set a breakpoint.
  4. From the Debug menu, choose Processes and attach to BTSNTSvc.exe. (Have more than one?) Choose CLR debugging only - not native. The symbols should be loaded automatically - no need to copy PDBs to the GAC for this case.
  5. Trigger your orchestration however you normally would.
  6. Find your problem, Debug-Detach All, and fix the problem in the orchestration.
  7. Decide that you really want Gilles' MessageContext Debugger Visualizer

There is another benefit to having the generated C# files for orchestrations be more accessible...If you deploy your PDBs to the GAC, either using either my upcoming deployment work for BizTalk 2006 or just the GetGacPath2 utility that I made available here, you will find that stack traces that are recorded in the event log actually reference line numbers within the generated C# code.

As I said in an earlier post, if you are responsible for troubleshooting BizTalk applications in production, you are likely hungry for all the information you can get about why something is failing.  Since all BizTalk project assemblies are in the GAC, the stack traces you get (either from your own logging, or the event logs BizTalk generates for unhandled exceptions) do not contain file and line number information by default.  This makes post-mortem analysis a lot harder...

When a BizTalk 2006 application is deployed to production, you might consider archiving the generated C# code for production support.  If you use GetGacPath2 to put PDBs in the GAC, you will have file and line number information within captured stack traces to aid in troubleshooting. (Note that GetGacPath2 supports MSIL, 32 bit, and 64 bit assembly caches.  MSIL is the right choice for BizTalk 2006 projects.)

Friday, June 23, 2006 11:20:03 AM (Central Standard Time, UTC-06:00)  #    Comments [0] -
BizTalk Insights
Archive
<December 2006>
SunMonTueWedThuFriSat
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456
About the author:

Scott Colestock lives, writes, and works as an independent consultant in the Twin Cities (Minneapolis, Minnesota) area.

© Copyright 2008
Scott Colestock
Sign In
All Content © 2008, Scott Colestock
DasBlog theme 'Business' created by Christoph De Baene (delarou)