ActiveMQ Artemis Message Counter Example

# JMS Message Counter Example

    To run the example, simply type mvn verify from this directory,
    or mvn -PnoServer verify if you want to start and create the server manually.

This example shows you how to use message counters to obtain message information for a JMS queue.

The example will show how to configure sampling of message counters.
We will produce and consume 1 message from a queue. Interleaved with the JMS operation, we will retrieve the queue's message counters at different times to display the metrics on the queue.

## Example setup

Message counter is configured in the server configuration file broker.xml:

             <message-counter-enabled>true</message-counter-enabled>
             <message-counter-sample-period>2000</message-counter-sample-period>
             <message-counter-max-day-history>2</message-counter-max-day-history>

By default, Message counter is not enabled (for performance reason). To enable them, set `message-counter-enabled` to `true`.
Queues are sampled every 10 seconds by default. For this example we will reduce it to 2 seconds by setting `message-counter-sample-period` to `2000`.
ActiveMQ Artemis holds in memory the message counters' history for a maximum number of days (10 by default). We can change the number of days the history is kept by setting the `message-counter-max-day-history` parameter.

The sample period and the max day history parameters have a small impact on the performance of ActiveMQ Artemis (the resources taken to sample a queue are not available to the system's normal use). You should set these parameters accordingly to the use and throughput of your messages.

## Example step-by-step

1. First we need to get an initial context so we can look-up the JMS connection factory and destination objects from JNDI. This initial context will get it's properties from the `client-jndi.properties` file in the directory `../common/config`

               InitialContext initialContext = getContext();

2. We look up the JMS queue object from JNDI

               Queue queue = (Queue) initialContext.lookup("/queue/exampleQueue");

3. We look up the JMS connection factory object from JNDI

               ConnectionFactory cf = (ConnectionFactory) initialContext.lookup("/ConnectionFactory");

4. We create a JMS connection, session and producer for the queue

                connection = cf.createQueueConnection();
                QueueSession session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
                MessageProducer producer = session.createProducer(queue);

5. We create and send a JMS text message

                TextMessage message = session.createTextMessage("This is a text message");
                producer.send(message);
                System.out.println("Sent message: " + message.getText());

6. We will now sleep a little bit to be sure the queue is sample. Since we have configure the sample period to be 2 seconds, we will sleep for 3 seconds to be sure that a sample is taken

                System.out.println("Sleep a little bit to have the queue sampled...");
                Thread.sleep(3000);

We now need to retrieve the message counters. They're available from the JMS Queue management resource. In this example, we will retrieve them using JMX (see the JMX example for a more complete description). You can also use JMS message to retrieve them (see the Management example to learn about managing ActiveMQ Artemis using JMS messages).

7. We retrieve the JMX MBean used to manage the JMS queue

                ObjectName on = ObjectNameBuilder.DEFAULT.getJMSQueueObjectName(queue.getQueueName());
                JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL(JMX_URL), new HashMap());
                MBeanServerConnection mbsc = connector.getMBeanServerConnection();
                JMSQueueControl queueControl = (JMSQueueControl)MBeanServerInvocationHandler.newProxyInstance(mbsc,
                                                                                                  on,
                                                                                                  JMSQueueControl.class,
                                                                                                  false);

8. We retrieve the message counter and display them. MessageCounters are retrieved as `JSON Strings` for portability reason (whether JMX is used for management or JMS messages). To make it simpler to use them in the code, there is a `MessageCounterInfo` data structure.

                String counters = queueControl.listMessageCounter();
                MessageCounterInfo messageCounter = MessageCounterInfo.fromJSON(counters);>

9. We display the message counters

                displayMessageCounter(messageCounter);

The message counter contains a variety of metrics on the queue which is sampled (total messages added to the queue, current depth of the queue, deltas since the last sample, timestamp of the last message added, timestamp of the last sample, etc.)

                private void displayMessageCounter(MessageCounterInfo counter)
                {
                   System.out.format("%s (sample updated at %s)\n",  counter.getName(), counter.getUdpateTimestamp());
                   System.out.format("   %s message(s) added to the queue (since last sample: %s)\n", counter.getCount(),
                                                                                                      counter.getCountDelta());
                   System.out.format("   %s message(s) in the queue (since last sample: %s)\n", counter.getDepth(),
                                                                                                counter.getDepthDelta());
                   System.out.format("   last message added at %s\n\n", counter.getLastAddTimestamp());
                }

10. We sleep again to have the queue sampled

                System.out.println("Sleep a little bit again...");
                Thread.sleep(3000);

11. We list the message counters again

                counters = queueControl.listMessageCounter();
                messageCounter = MessageCounterInfo.fromJSON(counters);
                displayMessageCounter(messageCounter);

We will now consume a message from the queue before listing a last time the message counters

12. We create a consumer for the queue

                MessageConsumer consumer = session.createConsumer(queue);

13. We start the connection to receive messages on the consumer

               connection.start();

14. We receive a message from the queue

               TextMessage messageReceived = (TextMessage)consumer.receive(5000);
               System.out.format("Received message: %s\n\n", messageReceived.getText());

15. We sleep one last time to have the queue sampled

                System.out.println("Sleep a little bit one last time...");
                Thread.sleep(3000);

16. We list the message counters a final time (this time with no message in the queue)

                counters = queueControl.listMessageCounter();
                messageCounter = MessageCounterInfo.fromJSON(counters);
                displayMessageCounter(messageCounter);

17. And finally, always remember to close your JMS connections and resources after use, in a `finally` block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects

               finally
               {
                  if (initialContext != null)
                  {
                    initialContext.close();
                  }
                  if (connection != null)
                  {
                     connection.close();
                  }
               }

- User Manual's Message Counters chapter
- MessageCounterInfo is a helper class used to create a MessageCounterInfo object from the JSON String which represents message counters