Tech Tip: Finding the statistic you’re after.

The power of iControl is wrapped in its flexibility. That means more power, it also means more work. One question has come up repeatedly, and after the last round on the forums, I figured it would make an excellent Tech Tip.

One issue that came up for me, and has come up for at least two users I’ve talked to is the use of the get_statistics() interfaces. These interfaces allow you to get an amazing amount of data about just about any BIG-IP object on your system. The problem comes in when you want a single data value – not only does the system allow you to get an amazing amount of data, it requires you to.

When you call get_statistics, an array of Common.Statistics objects is returned. Each of these has a statistic type, a 64-bit value, and a time stamp telling when the statistics were taken.

In a nutshell, you have dozens of responses, each with the data you want, with a name that is nested two objects deep. You need to figure out which one of those is right for you.

The easiest and most obvious manner of doing this is to walk through the list with a for loop, checking the statistic type to find the one you need. Statistic types and their meanings are well documented on the DevCentral Wiki, here

To get all of this set up, we’ll document the calls required here. I will use Java, but the calls are not significantly different in other languages except for Perl which requires some extra work to do Web Services. I am also using the Pool interface, but the get_statistics() routine behaves the same no matter what object you’re calling it for.


 

LocalLBPoolPoolStatistics ret = null;
    LocalLBPoolBindingStub stub = null;
    // Get a connection to the LBPool services on the BIG-IP and ask it for statistics.
    try {
        stub = (LocalLBPoolBindingStub) new LocalLBPoolLocator().getLocalLBPoolPort(new java.net.URL(endpoint));
        stub.setTimeout(6000);
        ret = stub.get_statistics(pools);
    } catch(Exception e) {
        System.out.println(e.getLocalizedMessage());
    }

Assuming that the value of pools was a a single pool name in element zero, we now have an array of pool statistics in ret that are relevant to that pool name. If pools was multiple names it is a bit more complex, but not too much – we have an array of statistics in ret that includes elements from each pool name in pools. 

Let’s take a moment and examine the LocalLB::Pool::Statistics class, because it’s only intuitive if you already know what it does. This class is an object that wraps an array of responses, one per pool in the “pools” parameter passed in above. If you only have one pool in the request, it will only contain one entry in the PoolStatisticsEntry[] array. There is a one-to-one relationship, but it is one element of the PoolStatistics.statistics member, not of the input and return values.

With that said, each PoolStatisticEntry element has a pool_name String that you can compare to the pool you’re currently looking for to find the right one. In the simplest case, that would be: 

 

for(int x = 0; x < ret.statistics.length; x++)
     if(ret.statistics[x].pool_name.compareTo(myPoolName))
        break;

Now ret.statistics[x] should hold the data for your pool, assuming myPoolName is in the result set… Which it will be if (a) it is a valid pool name, and (b) it was passed in to get_statistics() as part of the array.

Now you can get a reference to the correct set of statistics – the ones for myPoolName with the following line:

 

LocalLBPoolStatisticEntry myStats = ret.statistics[x];

That doesn’t get you the answer though, remember that myStats in this case is a list of many statistical values, and you’re likely only seeking one or two. Confusingly, the elements of this array take the same name as the array we just pulled myStats from… statistics. That’s okay, we’ve got the context by creating the myStats variable.

There is an excellent reference to the list of possible values on the DevCentral Wiki: Statistic types

Once you know which of these types you’re after, you can then walk through the list and find it by comparing myStats.statistics[NN] to your static value. Alternatively, if your language supports collections you can cast the Vector you receive to a sorted collection or a dictionary and then just grab the value you are after.

Here’s the rub, both the string name (as the field name) and the value (as the field value) come back from the BIG-IP, so if you build a dictionary, be certain to tell it which you want to key off of. 

References

The Devcentral iControl Wiki  is an excellent reference for the iControl interface. Using iControl with Java is covered in a Tutorial, and an overview of how to use iControl is here

Finally, Joe had a pretty thorough answer to this question on the forums - for those already familiar with the basics of the various get_statistics calls here.