I wanted to use Opentelemetry with MQ. One option is to use JMS, and the “code free” Otel support.
This code-free-support intercepts the send and receive methods, intercepts them, and sets up the Otel support (in MQ).
See here for information on the Java Otel instrumentation.
My code
I used the IBM MQ sample JMS programs JMSProducer and JMSConsumer.
export CLASSPATH=/opt/mqm/java/lib/com.ibm.mq.allclient.jar:$CLASSPATH
export CLASSPATH=/opt/mqm/samp/jms/samples:$CLASSPATH
export CLASSPATH=/home/colin/Downloads/opentelemetry-javaagent.jar:$CLASSPATH
export OTEL_JAVAAGENT_ENABLED=true
export OTEL_JAVAAGENT_LOGGING=simple
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_ENDPOINT=http://10.1.0.2:4317
java -javaagent:/home/colin/Downloads/opentelemetry-javaagent.jar
-Dotel.resource.attributes=service.name=ColinsJMS
-Dotel.traces.exporter=console
/opt/mqm/samp/jms/samples/JmsProducer.java \
-m MQPA -d RSERVER -l SYSTEM.DEF.SVRCONN -h 172.26.1.2 -p 2414
This produced
Jaeger output

Which shows the message passed through MQ and was got (by the server program).
Because the sample JMS program does not allow you to specify a ReplyToQueue manager name, the server cannot send the reply back.
I changed the JMSProducer to specify a replyToQueue, and pass this as part of the message.
I used the JMSConsumer program unchanged.
The updated application
export CLASSPATH=/opt/mqm/samp/jms/samples:$CLASSPATH
export CLASSPATH=/home/colin/Downloads/opentelemetry-javaagent.jar:$CLASSPATH
export OTEL_JAVAAGENT_ENABLED=true
# export OTEL_JAVAAGENT_LOGGING=simple # default
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_LOGS_EXPORTER=console
export OTEL_METRICS_EXPORTER=console
export OTEL_EXPORTER_OTLP_ENDPOINT=http://10.1.0.2:4317
java -javaagent:/home/colin/Downloads/opentelemetry-javaagent.jar \
-Dotel.resource.attributes=service.name=ColinsJMSProducer \
-Dotel.traces.exporter=console \
/opt/mqm/samp/jms/samples/colinProducer.java \
-m MQPA -d RSERVER -l SYSTEM.DEF.SVRCONN -h 172.26.1.2 -p 2414 -r CCOLIN
echo "===================================================="
java -javaagent:/home/colin/Downloads/opentelemetry-javaagent.jar \
-Dotel.resource.attributes=service.name=ColinsJMSConsumer \
-Dotel.traces.exporter=console \
/opt/mqm/samp/jms/samples/JmsConsumer.java \
-m MQPA -d CCOLIN -l SYSTEM.DEF.SVRCONN -h 172.26.1.2 -p 2414
When this ran, the Otel data displayed in Jaeger was

Comments on the output.
- The chart shows
- A message is put to an MQ remote queue called RSERVER on queue manager MQPA. This operation takes 20.2 milliseconds.
- The message is got from a queue called CSQ9 (a transmission queue). This flows over the network to queue manager CSQ9.
- The message is put to a queue CSERVER on queue manager CSQ9.
- An application on CSQ9 gets the message, does some processing and puts a reply to queue CCOLIN ( on queue manager MQPA). You cannot see this program in the trace.
- The mover on CSQ9 gets the message from the transmission queue YMQPA and sends it over the network
- The mover on CSQ9 puts the message to queue CCOLIN
- The above processing is very quick.
- The putting JMS program ends, and starts the JMSConsumer program.
- 3.2 seconds after the initial put, the JMSConsumer program gets the message (and the MQGET takes 3.6 ms). The start of the second Java program takes a long time (most of this 3.2 seconds)
- There are no entries for the JMS programs themselves. There are only entries for the MQ on z/OS.
- Although there were two JMS Java programs involved – the Jaeger output just shows the MQ processing
What next?
Although this has shown that you can easily add Otel processing to your JMS program, the output is lacking.
You can manually instrument your Java program, as described by the Opentelemetry documentation.