Monitoring queue statistics in MQ

30 April, 2007 – 4:55 pm

When load testing MQ you are no doubt going to need to be able to monitor queue statistics in terms of how many messages have been enqueued and dequeued within a given timeframe. You can use native runmqsc commands to query queues in order to find current queue depths but this is just a snapshot in time. In order to be able to monitor how many messages have been or gone, you need to sample the queue over time. Here is a good synopsis of options…

A good way to achieve this is my using the PCF support package provided by IBM.

The WebSphere MQ Programmable Command Formats (PCF) provide the capability to perform administration tasks on a queue manager by sending and receiving WebSphere MQ messages of a special format. PCF request messages are sent to the queue manager’s command queue, where they are processed by the command server and replies returned to the designated reply-to queue.

This SupportPac contains a set of Java classes representing PCF header structures as well as an agent that can be used to simplify the task of communicating with a target queue manager and thus enable the use of WebSphere MQ Programmable Command Formats for queue manager administration.

Using a simple java object as documented in sample code, you can query queue stats of your choice. My implementation simply prints out the queue you are connected to, along with enqueue, dequeue and total queue size stats over an arbitrary time frame (eg. last 2 seconds). This can easily be called from a simple shell script.


ResetQStats.java

/**
* Reset MQ Queue Statistics (ResetQStats)
*
* Compile  : javac -classpath com.ibm.mq.jar:connector.jar:jta.jar:com.ibm.mq.pcf-6.0.jar ResetQStats.java
 
* Package  : jar cfm ResetQStats.jar ResetQStats.MF *.class
* Execute  : java -cp com.ibm.mq.jar:connector.jar:jta.jar:com.ibm.mq.pcf-6.0.jar:ResetQStats.jar ResetQStats [options]  
* Usage    : ResetQStats [options]
* Options  :
    host    MQ hostname eg. 127.0.0.1
    port          MQ port eg. 1415
    channel    MQ channel eg. CHANNEL_NAME
    queue    MQ queue eg. QUEUE_NAME
*
* Last edited  : 6 Mar 07 14.00
* Author    : Tim Koopmans
**/
 
import java.io.*;
import com.ibm.mq.*;
import com.ibm.mq.pcf.*;
 
public class ResetQStats
{
  final public static String copyright =
                  "Copyright (c) IBM Corp. 2005 All rights reserved.";
 
  public static void main (String [] args)
  {
           PCFAgent      agent;
    PCFParameter [] parameters = { new MQCFST (CMQC.MQCA_Q_NAME,args [3]) };
    MQMessage []    responses;
    MQCFH        cfh;
    PCFParameter    p;
 
    try
    {
         // Connect a PCFAgent to the specified queue manager
      if (args.length == 1)
      {
        agent = new PCFAgent (args [0]);
      }
      else
      {
        agent = new PCFAgent (args [0], Integer.parseInt (args [1]), args [2]);
      }
 
      // Use the agent to send the request
 
      responses = agent.send (CMQCFC.MQCMD_RESET_Q_STATS, parameters);
      cfh = new MQCFH (responses [0]);
 
      if (cfh.reason == 0)
      {
        //System.out.println ("Queue Statistics:");
        for (int i = 0; i < cfh.parameterCount; i++)
        {
          // Walk through the returned attributes
          p = PCFParameter.nextParameter (responses [0]);
          int parm = p.getParameter();
          switch (parm)
          {
            case CMQC.MQCA_Q_NAME:
                          //Queue Name
                          break;
            case CMQC.MQIA_TIME_SINCE_RESET:
                          //TimeSinceReset t(sec)
                          break;
            case CMQC.MQIA_MSG_ENQ_COUNT:
                          //MsgEnqCount ++
                      break;
            case CMQC.MQIA_MSG_DEQ_COUNT:
                          //MsgDeqCount --                      break;
            case CMQC.MQIA_HIGH_Q_DEPTH:
                          //HighQDepth  (total)
                      break;
          }
          System.out.print(" \t" + p.getValue ());
        }
        System.out.print("\n");
      }
      else
      {
        System.out.println ("PCF error:\n" + cfh);
        // Walk through the returned parameters describing the error
        for (int i = 0; i < cfh.parameterCount; i++)
        {
          System.out.println (PCFParameter.nextParameter (responses [0]));
        }
      }
 
      // Disconnect
      agent.disconnect ();
    }
 
    catch (ArrayIndexOutOfBoundsException abe)
    {
      System.out.println ("Usage: \n" +
        "\tjava ResetQStats queue-manager\n" +
        "\tjava ResetQStats host port svrconn-channel");
    }
 
    catch (NumberFormatException nfe)
    {
      System.out.println ("Invalid port: " + args [1]);
      System.out.println ("Usage: \n" +
        "\tjava ResetQStats queue-manager\n" +
        "\tjava ResetQStats host port svrconn-channel");
    }
 
    catch (MQException mqe)
    {
      System.err.println (mqe);
    }
 
    catch (IOException ioe)
    {
      System.err.println (ioe);
    }
  }
}

Simple Shell Script

#~/bin/sh
javac -classpath $HOME/harness/CDE/com.ibm.mq.jar:$HOME/harness/CDE/connector.jar:$HOME/harness/CDE/jta.jar:/home/strata/d281447/harness/CDE/com.ibm.mq.pcf-6.0.jar $HOME/harness/CDE/ResetQStats.java
cd $HOME/harness/CDE
jar cfm ResetQStats.jar ResetQStats.MF *.class
rm $HOME/harness/CDE/*.class
 
cd $HOME/harness/CDE
 
printf "\tQueue Name\t\t\t\t\t\t++ \t-- \tdepth \tsecs\n"
 
duration=$2  #duration in seconds
sampleRate=$3   #sample every n seconds
 
i="1"
while [ $i -le $duration ]
do
  java -cp com.ibm.mq.jar:connector.jar:jta.jar:com.ibm.mq.pcf-6.0.jar:ResetQStats.jar ResetQStats 127.0.0.1 1415 CHANNEL $1
  
  sleep $sampleRate
  i=`expr $i + 1`
 
done
printf "\n"

Share it: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Netscape
  • Reddit
  • Slashdot
  • Technorati
  • YahooMyWeb

Post a Comment

*
To prove that you're not a bot, enter this code
Anti-Spam Image