OpenTracing JMS Instrumentation
OpenTracing instrumentation for JMS.
Installation
JMS 1
pom.xml
<dependency>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-jms-1</artifactId>
<version>VERSION</version>
</dependency>
JMS 2
pom.xml
<dependency>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-jms-2</artifactId>
<version>VERSION</version>
</dependency>
Spring JMS
pom.xml
<dependency>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-jms-spring</artifactId>
<version>VERSION</version>
</dependency>
You most likely need to exclude spring-jms and spring-context dependencies and add own (to avoid jar hell):
<dependency>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-jms-spring</artifactId>
<version>VERSION</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>required version</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>required version</version>
</dependency>
Usage
// Instantiate tracer
Tracer tracer = ...
JMS API
// decorate JMS MessageProducer with TracingMessageProducer
TracingMessageProducer producer = new TracingMessageProducer(messageProducer, tracer);
// decorate JMS JMSProducer with TracingJMSProducer need Session
Session session = ...
TracingJMSProducer producer = new TracingJMSProducer(jmsProducer, session, tracer);
// or with JMSContext
JMSContext jmsContext = ...
TracingJMSProducer producer = new TracingJMSProducer(jmsProducer, jmsContext, tracer);
// decorate JMS MessageConsumer with TracingMessageConsumer
TracingMessageConsumer consumer = new TracingMessageConsumer(messageConsumer, tracer);
// decorate JMS MessageListener if used with TracingMessageListener
TracingMessageListener listener = new TracingMessageListener(messageListener, tracer);
consumer.setMessageListener(listener);
// send message
Message message = ...
producer.send(message);
// receive message
Message message = consumer.receive();
Spring JMS
// create TracingJmsTemplate which extends Spring JmsTemplate
JmsTemplate jmsTemplate = new TracingJmsTemplate(connectionFactory, tracer);
// send and receive messages as usual
jmsTemplate.send(...)
jmsTemplate.convertAndSend(...);
jmsTemplate.receive(...)
jmsTemplate.receiveAndConvert(...);
...
If @JmsListener
is used then it is required to import TracingJmsConfiguration e.g.
@Configuration
@Import(TracingJmsConfiguration.class)
@EnableJms
public class JmsConfiguration {
...
}
Java 9+
Modules opentracing-jms-1 and opentracing-jms-2 have next Automatic-Module-Name accordingly:
- io.opentracing.contrib.jms1
- io.opentracing.contrib.jms2
OpenTracing Conventions
Message properties
When a message exchange between a producer and consumer is traced using an OpenTracing compliant tracer, the trace context and any defined baggage items will be carried in the JMS message properties.
OpenTracing does not place any restrictions on the names used for the trace context and baggage item properties. However the JMS API does not permit the hyphen/dash -
character to be used. Therefore, it is necessary to encode the trace context and baggage item names.
The steps used to encode the key names are:
- replace any
-
character with__dash__
When the message is consumed, the steps are reversed to decode the original key names.
Any libraries that instrument the JMS API should conform to this convention to enable tracing interoperability.