Creating a Ini Check based on a WMI PerfRawData Class

For data in most PerfRawData classes the data you see by browsing the classes directly can be somewhat meaningless. You actually need to calculate meaningful values. If you do this correctly you can get very accurate information about various things. For example, the CPU utilisation is contained withing a PerfRawData WMI Class. If we get the raw CPU utilisation value, wait a bit and then get it again and if we know exactly how long it was between our 2 WMI calls, we can very accurately calculate the CPU utilisation between those 2 points in time. This is exactly how this plugin handles data like that. There is one WMI call made per run of the plugin. The second time you call the plugin, the information is calculated using the point-in-time information you collected the last time you ran, and, for CPU utilisation you get accurate information about the CPU utilisation between the 2 runs of the plugin.

Not all of the values contain in the PerfRawData classes need calculation, but lots and lots of them do require it.

So using the RawPerfData classes can be a very good way of obtaining very detailed information.

To show you how to do this we are going to run through an example.

Collecting the Prerequisite Information

Firstly you need to find the Raw Data class you want to obtain the information from. For this example we are going to use the Class for stats on IIS Users, Win32_PerfRawData_W3SVC_WebService.

Now we have to find the WMI Reference documentation for that class. Its here ->
http://msdn.microsoft.com/en-us/library/aa394345%28v=vs.85%29 and you can also access the other classes using the left hand menu.

Read through the field descriptions and note down the fields you want to collect data for.
In this example, we choose:
AnonymousUsersPerSec with a CounterType 272696320
CurrentAnonymousUsers with a CounterType 65536

Open up the Counter Type Reference http://msdn.microsoft.com/en-us/library/aa389383%28v=vs.85%29 and note down the CookingType for each field. So far our list looks like,
AnonymousUsersPerSec with a CounterType 272696320 and a CookingType of PERF_COUNTER_COUNTER
CurrentAnonymousUsers with a CounterType 65536 and a CookingType of PERF_COUNTER_COUNTER

The plugin needs to know how to handle this CookingType and it requires coding for each different one. So we have to make sure we have coded for this CookingType already by looking in the plugin for it (or documentation in sample.ini).
To find this out you can look though the code for PERF_COUNTER_COUNTER. We are looking for a line like
} elsif ($function eq 'PERF_COUNTER_COUNTER' in the calc_new_field function
In this case we have coded for it already.

If we had not coded for it already, the calculation for that countertype will need to be added to the plugin. For that we'd need to refer to the calculation methods for each counter type here: http://technet.microsoft.com/en-us/library/cc757032%28v=ws.10%29. But doing that coding is beyond the scope of this particular article.

So now we know that we can calculate this CookingType correctly over time, between WMI calls.

Start the Ini File Section

Now lets start to set up the ini file section for this. Lets give it a section name.
[checkiis anonusers] - this will be accessed from the command line using -m checkiis -s anonusers

Define the Query

Now lets define our WMI query. We want the query to return us only one row of data. We note that the data in this class has multiple rows or instances. Its actually one per web site defined. The WMI field "Name" distinguishes between the various web sites. There is also a predefined "instance" called "_Total", this gives us stats on all the instances combined. So we need to define which instance we are interested in. We could hardcode that or pass it in via the command line. We'll pass it via the command line using -a INSTANCENAME, this is called arg1, the first argument.

The data we need as a minimum for the calculations we have to perform are the fields we are interested in plus the timestamp information so we can tell how far apart our 2 queries are. So that's
AnonymousUsersPerSec and CurrentAnonymousUsers for the data and for the timestamp information we need
Timestamp_Sys100NS and Frequency_Sys100NS.
How did we know we needed those 2 timestamp related fields? By reading the documentation for the specific CookingType. The CookingType of PERF_COUNTER_COUNTER uses
Formula = (Nx - N0) / ((Dx - D0) / F)
where D is is Timestamp_Sys100NS and F is Frequency_Sys100NS

So if we need these 4 fields we could just ask for them (comma delimited list) or just ask for everything in the class (use *).
We'll just ask for everything.

Our query then becomes:
query=SELECT * FROM Win32_PerfRawData_W3SVC_WebService where Name = "{_arg1}"

We use the {_arg1} so that the value we pass in from -a INSTANCENAME gets substituted into the query when it is performed.
So if we run the plugin with -a MYSITE the actual WMI query performed would be
SELECT * FROM Win32_PerfRawData_W3SVC_WebService where Name = "MYSITE"

More Query Related Definitions

We need to define how many WMI samples we need. In this case, its 2 since the CookingType PERF_COUNTER_COUNTER (for AnonymousUsersPerSec) needs 2 data samples (from the CookingType documentation). The field CurrentAnonymousUsers only needs one sample. So overall since there is a field that needs 2 samples we have to go with 2 samples.
So that's
samples=2

We could define how far apart the queries are, but that's old school. That comes from when the plugin ran one WMI query, waited a bit and then ran the other WMI query. That way, meant more WMI calls per plugin run and only short samples of values. Yuk, we don't like that anymore. Now we just run the plugin whenever Nagios schedules it, do only one WMI call per run and calculate between runs. Its way better. You might see some old definitions of
delay=5 in some ini files. Its not needed anymore.

Calculating the Fields

Now we want to define how to perform the custom calculations to obtain our data. Our naming convention for calculated fields is to start them with an _ and then use the same name as the original field.

In our example, the CookingType PERF_COUNTER_RAWCOUNT does not need any calculation. We only have to calculate for PERF_COUNTER_COUNTER

So here the custom calc simply specifies -

  • The new field name
  • The CounterType
  • The original field name
  • The format for display of the result

and the ini file declaration is
customfield=_AnonymousUsersPersec,PERF_COUNTER_COUNTER,AnonymousUsersPersec,%.0f
This creates a new field called _AnonymousUsersPersec which contains our correctly calculated value.

Define the Fields Displayed

The example we are using only returns one row of WMI data. So we don't need the predisplay defintion.
We just simply define one line of output showing all our data.

We like starting all our checks with
display=_DisplayMsg||~|~| - ||
since this displays a nice consistent format that tells us the status (Warn/Critical) and which field and warn/critical criteria triggered it.

For this example, we'd also like to show the name of the web site. This is the Name field.
There is some documetation in sample.ini on how this display field format works.
display=Name||Site Name="|~|||"

Next we want to show our 2 fields of interest. We use a simpler format method for these.
Note how we use the calculated field, not the raw field.
display=_AnonymousUsersPersec|#/sec
and
and then the raw field (since it did not need calculation)
display=CurrentAnonymousUsers|#

Define the Fields We Can Warn/Critical against

We want to be able to define warn/critical criteria against both the example fields so we simply list both of them
Note how we use the calculated field, not the raw field.
test=_AnonymousUsersPersec
and then the raw field (since it did not need calculation)
test=CurrentAnonymousUsers

Define the Fields Providing Performance Data

Now define both of our example fields to also return performance data so we can draw nice graphs.
Sample.ini contains more info about using this ini file setting, but in this example we just use the simple format.
Note how we use the calculated field, not the raw field.
perf=_AnonymousUsersPersec
and then the raw field (since it did not need calculation)
perf=CurrentAnonymousUsers

The Complete Ini Check

Now taking all the definitions we have, out ini file check should look like (the order of line is not important except to look consistent):

[checkiis anonusers]
query=SELECT * FROM Win32_PerfRawData_W3SVC_WebService where Name = "{_arg1}"
samples=2
customfield=_AnonymousUsersPersec,PERF_COUNTER_COUNTER,AnonymousUsersPersec,%.0f
test=_AnonymousUsersPersec
test=CurrentAnonymousUsers
display=_AnonymousUsersPersec|#/sec
display=CurrentAnonymousUsers|#
perf=_AnonymousUsersPersec
perf=CurrentAnonymousUsers

Now, give me a second while I put that in an ini file and try it out.
Oh, hang on, I can't test this at the moment since I need some more RAM for my ESX box so I can run my test IIS server.
Oh well, I think its right.
So you'd execute it like:
check_wmi_plus.pl -H xp0 -m checkiis -s anonusers -u USER -p PASS -a MYSITE
to get the info from the web site called MYSITE.

If I wanted to get the info for all the websites I'd use:
check_wmi_plus.pl -H xp0 -m checkiis -s anonusers -u USER -p PASS -a _total