The Fundamentals: #3 Instrumentation and Probing

Today, instrumentation and probing of applications is difficult.  Once an application is running, the ability to probe the runtime state of the appliction is hard.  When administrators and developers are trying to troubleshoot why a given application is having a problem, their hands are often tied behind their backs as far as the tools at their disposal.  And, if they were to want to "fix" the application while it was still running so as to get it out of a bad state, they are definitely at a loss. 

The main way to provide this kind of functionality today is to write a custom WMI provider, which isn't a trivial task.  It involves some heavy duty COM programming. One goal for Longhorn is to improve the situation, so that applications can be set up for instrumentation and probing at designtime with relative ease.  Then, at runtime, administrators will be able to do the types of investigation and actions that they need to in order to keep applications up and running.

Through the use of attributes on managed code, application developers will now be able to instrument their applications without much work.  By simply adding a reference to the System.Management.Instrumentation namespace, they can apply the appropriate attributes to any class or method suitable for instrumentation.  For example, classes that are to be exposed to the instrumentation would receive the [Folder] attribute:

 [Folder]
public class MyApp
{
...
}
[Folder]
public class RequestQueues
{
...
}

And, a method suitable for probing or invoking would receieve the [Probe] attribute:

 [Probe(ResultType=typeof(int))]
public object[] Contents()
{
...
}

That's it from the developer perspective. 

For an administrator, it is a matter of discovering which applications are available for probing and then using tools to actually inspect the application.  A tool that does just this ships with Longhorn called wmicmd.exe.  For example to get the contents of the above code snippet, the cmd would look as follows:

wmicmd /get:#System/Apps/MyApp/MyId=<ID>/MyApp/RequestQueue/Contents

You can see how the attributes on the classes and methods manifest as a way to uniquely path to methods in the application. 

The best way to get a sense of this is to try it out for yourself.

1. Open the Longhorn SDK Samples and navigate to the WMI tree. Download the SampleRequestQueueApp application.  This is a simple application that keeps a list of integers in memory, allowing the user to add/delete from the list.  The source code for the application is can be seen here.  Notice the [Folder] and [Probe] attributes.

2. Compile the application using msbuild by opening a Longhorn SDK Commandline, navigating to the folder where the source code is located and typing msbuild.

3. Next you will need to generate an instrumentation manifest for this executable. (This step will eventually go away.)  Navigate to the directory containing the executable generated by msbuild and type

wmimgen SampleRequestQueueApp.exe

4. Then, copy the manifest to the following location as follows:

copy SampleRequestQueueApp.manifest %WINDIR%\system32\wbem\manifest

5. Now run the executable. Press "a" to add some integers.

6. Open a second Longhorn SDK Commandline window. Type wmicmd. You will see a list of switches for this tool.

7. First try:

wmicmd /s:*

This will display all the available applications and probes at your disposal.  On my machine, the following is emitted:

#System/Drive/Name=_
#System/Drive/GetAll
#System/Drive/Name=_/VolumeLabel=_
#System/Drive/GetAll/DriveName=_/VolumeLabel=_
#System/Drive/Name=_/Cleanup
#System/Drive/GetAll/DriveName=_/Cleanup
#System/Drive/Name=_/VolumeLabel
#System/Drive/GetAll/DriveName=_/VolumeLabel
#System/Drive/Name=_/SectorsPerCluster
#System/Drive/GetAll/DriveName=_/SectorsPerCluster
#System/Drive/Name=_/BytesPerSector
#System/Drive/GetAll/DriveName=_/BytesPerSector
#System/Drive/Name=_/FreeClusters
#System/Drive/GetAll/DriveName=_/FreeClusters
#System/Drive/Name=_/TotalClusters
#System/Drive/GetAll/DriveName=_/TotalClusters
#System/Drive/Name=_/PercentFree
#System/Drive/GetAll/DriveName=_/PercentFree
#System/Drive/Name=_/DriveName
#System/Drive/GetAll/DriveName=_/DriveName
#System/Apps/MyApp/MyId=*
#System/Apps/MyApp/MyId=_/MyApp/RequestQueue
#System/Apps/MyApp/MyId=_/MyApp/RequestQueue/Contents
#System/Apps/MyApp/MyId=_/MyApp/RequestQueue/DeleteItem
#System/Apps/MyApp/MyId=_/MyApp/RequestQueue/MaxConcurrentRequests
#System/Apps/MyApp/MyId=_/MyApp/RequestQueue/MaxConcurrentRequests=_

You can see that there are already some providers above and beyond our sample app. 

8. In fact, just for kicks, type

wmicmd /get:#System/Drive/GetAll

This will list all the drives on the machine, with statistics about free clusters, etc.

9. Getting back to our application, type the following:

wmicmd /get:#System/Apps/MyApp/MyId=*

On my machine, this returned:

<WMIResults>
<String_Collection>
<String>#system/apps/myapp/myid=2548</String>
</String_Collection>
</WMIResults>

Because there could be multiple instances of the executable running, I need to get the ID of the one I want to probe.  In this case, it is instance 2548.  Of course, it will be different on your machine.

10. Now that we have the instance id, we can begin probing.  In fact, we can see what probes we can run from our initial wmicmd that listed all the probes.  So, let's try:

wmicmd /get:#System/Apps/MyApp/MyId=2548/MyApp/RequestQueue/Contents

On my machine, this returns:

<WMIResults>
<ArrayOfAnyType>
<anyType xsi:type="xsd:int" xmlns:xsi="https://www.w3.org/2001/XMLSchema-
instance">80</anyType>
<anyType xsi:type="xsd:int" xmlns:xsi="https://www.w3.org/2001/XMLSchema-
instance">87</anyType>
<anyType xsi:type="xsd:int" xmlns:xsi="https://www.w3.org/2001/XMLSchema-
instance">51</anyType>
</ArrayOfAnyType>
</WMIResults>

So, this probe was literally looking into the in memory stack of integers added to the list.  You can imagine invoking probes that not only return information, but actually change the state of the application.

This is just a taste of instrumentation in Longhorn.  Expect more in the future...