Skip to content

Commit ed0d790

Browse files
authored
GH-2814: OTel tags for RabbitTemplate and RabbitListener
Fixes: #2814 Issue link: #2814 * Add Opentelemetry tags `RabbitTemplate ` * Add Opentelemetry tags `RabbitListenerObservationConvention`
1 parent aa21c73 commit ed0d790

File tree

3 files changed

+113
-22
lines changed

3 files changed

+113
-22
lines changed

spring-rabbit/src/main/java/org/springframework/amqp/rabbit/support/micrometer/RabbitListenerObservation.java

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022 the original author or authors.
2+
* Copyright 2022-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -26,8 +26,8 @@
2626
* Spring Rabbit Observation for listeners.
2727
*
2828
* @author Gary Russell
29+
* @author Vincent Meunier
2930
* @since 3.0
30-
*
3131
*/
3232
public enum RabbitListenerObservation implements ObservationDocumentation {
3333

@@ -36,7 +36,6 @@ public enum RabbitListenerObservation implements ObservationDocumentation {
3636
*/
3737
LISTENER_OBSERVATION {
3838

39-
4039
@Override
4140
public Class<? extends ObservationConvention<? extends Context>> getDefaultConvention() {
4241
return DefaultRabbitListenerObservationConvention.class;
@@ -69,6 +68,34 @@ public String asString() {
6968
return "spring.rabbit.listener.id";
7069
}
7170

71+
},
72+
73+
/**
74+
* The queue the listener is plugged to.
75+
*
76+
* @since 3.2
77+
*/
78+
DESTINATION_NAME {
79+
80+
@Override
81+
public String asString() {
82+
return "messaging.destination.name";
83+
}
84+
85+
},
86+
87+
/**
88+
* The delivery tag.
89+
*
90+
* @since 3.2
91+
*/
92+
DELIVERY_TAG {
93+
94+
@Override
95+
public String asString() {
96+
return "messaging.rabbitmq.message.delivery_tag";
97+
}
98+
7299
}
73100

74101
}
@@ -86,8 +113,14 @@ public static class DefaultRabbitListenerObservationConvention implements Rabbit
86113

87114
@Override
88115
public KeyValues getLowCardinalityKeyValues(RabbitMessageReceiverContext context) {
89-
return KeyValues.of(RabbitListenerObservation.ListenerLowCardinalityTags.LISTENER_ID.asString(),
90-
context.getListenerId());
116+
final var messageProperties = context.getCarrier().getMessageProperties();
117+
return KeyValues.of(
118+
RabbitListenerObservation.ListenerLowCardinalityTags.LISTENER_ID.asString(), context.getListenerId(),
119+
RabbitListenerObservation.ListenerLowCardinalityTags.DESTINATION_NAME.asString(),
120+
messageProperties.getConsumerQueue(),
121+
RabbitListenerObservation.ListenerLowCardinalityTags.DELIVERY_TAG.asString(),
122+
String.valueOf(messageProperties.getDeliveryTag())
123+
);
91124
}
92125

93126
@Override

spring-rabbit/src/main/java/org/springframework/amqp/rabbit/support/micrometer/RabbitTemplateObservation.java

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022 the original author or authors.
2+
* Copyright 2022-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
2626
* Spring RabbitMQ Observation for {@link org.springframework.amqp.rabbit.core.RabbitTemplate}.
2727
*
2828
* @author Gary Russell
29+
* @author Vincent Meunier
2930
* @since 3.0
3031
*
3132
*/
@@ -68,8 +69,35 @@ public String asString() {
6869
return "spring.rabbit.template.name";
6970
}
7071

72+
},
73+
74+
/**
75+
* The destination exchange (empty if default exchange).
76+
* @since 3.2
77+
*/
78+
EXCHANGE {
79+
80+
@Override
81+
public String asString() {
82+
return "messaging.destination.name";
83+
}
84+
85+
},
86+
87+
/**
88+
* The destination routing key.
89+
* @since 3.2
90+
*/
91+
ROUTING_KEY {
92+
93+
@Override
94+
public String asString() {
95+
return "messaging.rabbitmq.destination.routing_key";
96+
}
97+
7198
}
7299

100+
73101
}
74102

75103
/**
@@ -85,8 +113,11 @@ public static class DefaultRabbitTemplateObservationConvention implements Rabbit
85113

86114
@Override
87115
public KeyValues getLowCardinalityKeyValues(RabbitMessageSenderContext context) {
88-
return KeyValues.of(RabbitTemplateObservation.TemplateLowCardinalityTags.BEAN_NAME.asString(),
89-
context.getBeanName());
116+
return KeyValues.of(
117+
TemplateLowCardinalityTags.BEAN_NAME.asString(), context.getBeanName(),
118+
TemplateLowCardinalityTags.EXCHANGE.asString(), context.getExchange(),
119+
TemplateLowCardinalityTags.ROUTING_KEY.asString(), context.getRoutingKey()
120+
);
90121
}
91122

92123
@Override

spring-rabbit/src/test/java/org/springframework/amqp/rabbit/support/micrometer/ObservationIntegrationTests.java

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022 the original author or authors.
2+
* Copyright 2022-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,7 +21,6 @@
2121
import java.util.List;
2222
import java.util.concurrent.CountDownLatch;
2323
import java.util.concurrent.TimeUnit;
24-
import java.util.stream.Collectors;
2524

2625
import org.springframework.amqp.core.Message;
2726
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
@@ -35,6 +34,7 @@
3534
import org.springframework.context.annotation.Bean;
3635
import org.springframework.context.annotation.Configuration;
3736

37+
import io.micrometer.common.KeyValue;
3838
import io.micrometer.common.KeyValues;
3939
import io.micrometer.core.tck.MeterRegistryAssert;
4040
import io.micrometer.observation.ObservationRegistry;
@@ -47,7 +47,6 @@
4747
/**
4848
* @author Artem Bilan
4949
* @author Gary Russell
50-
*
5150
* @since 3.0
5251
*/
5352
@RabbitAvailable(queues = { "int.observation.testQ1", "int.observation.testQ2" })
@@ -72,40 +71,69 @@ public SampleTestRunnerConsumer yourCode() {
7271
.hasSize(4);
7372
List<FinishedSpan> producerSpans = finishedSpans.stream()
7473
.filter(span -> span.getKind().equals(Kind.PRODUCER))
75-
.collect(Collectors.toList());
74+
.toList();
7675
List<FinishedSpan> consumerSpans = finishedSpans.stream()
7776
.filter(span -> span.getKind().equals(Kind.CONSUMER))
78-
.collect(Collectors.toList());
77+
.toList();
7978
SpanAssert.assertThat(producerSpans.get(0))
80-
.hasTag("spring.rabbit.template.name", "template");
79+
.hasTag("spring.rabbit.template.name", "template")
80+
.hasTag("messaging.destination.name", "")
81+
.hasTag("messaging.rabbitmq.destination.routing_key", "int.observation.testQ1");
8182
SpanAssert.assertThat(producerSpans.get(0))
8283
.hasRemoteServiceNameEqualTo("RabbitMQ");
8384
SpanAssert.assertThat(producerSpans.get(1))
84-
.hasTag("spring.rabbit.template.name", "template");
85+
.hasTag("spring.rabbit.template.name", "template")
86+
.hasTag("messaging.destination.name", "")
87+
.hasTag("messaging.rabbitmq.destination.routing_key", "int.observation.testQ2");
8588
SpanAssert.assertThat(consumerSpans.get(0))
86-
.hasTagWithKey("spring.rabbit.listener.id");
89+
.hasTagWithKey("spring.rabbit.listener.id")
90+
.hasTag("messaging.destination.name", "int.observation.testQ1")
91+
.hasTag("messaging.rabbitmq.message.delivery_tag", "1");
8792
SpanAssert.assertThat(consumerSpans.get(0))
8893
.hasRemoteServiceNameEqualTo("RabbitMQ");
8994
assertThat(consumerSpans.get(0).getTags().get("spring.rabbit.listener.id")).isIn("obs1", "obs2");
9095
SpanAssert.assertThat(consumerSpans.get(1))
9196
.hasTagWithKey("spring.rabbit.listener.id");
9297
assertThat(consumerSpans.get(1).getTags().get("spring.rabbit.listener.id")).isIn("obs1", "obs2");
98+
SpanAssert.assertThat(consumerSpans.get(1))
99+
.hasTagWithKey("spring.rabbit.listener.id")
100+
.hasTag("messaging.destination.name", "int.observation.testQ2")
101+
.hasTag("messaging.rabbitmq.message.delivery_tag", "1");
93102
assertThat(consumerSpans.get(0).getTags().get("spring.rabbit.listener.id"))
94103
.isNotEqualTo(consumerSpans.get(1).getTags().get("spring.rabbit.listener.id"));
95104

96105
MeterRegistryAssert.assertThat(getMeterRegistry())
97106
.hasTimerWithNameAndTags("spring.rabbit.template",
98-
KeyValues.of("spring.rabbit.template.name", "template"))
107+
KeyValues.of(
108+
KeyValue.of("spring.rabbit.template.name", "template"),
109+
KeyValue.of("messaging.destination.name", ""),
110+
KeyValue.of("messaging.rabbitmq.destination.routing_key", "int.observation.testQ1")
111+
)
112+
)
99113
.hasTimerWithNameAndTags("spring.rabbit.template",
100-
KeyValues.of("spring.rabbit.template.name", "template"))
114+
KeyValues.of(
115+
KeyValue.of("spring.rabbit.template.name", "template"),
116+
KeyValue.of("messaging.destination.name", ""),
117+
KeyValue.of("messaging.rabbitmq.destination.routing_key", "int.observation.testQ2")
118+
)
119+
)
101120
.hasTimerWithNameAndTags("spring.rabbit.listener",
102-
KeyValues.of("spring.rabbit.listener.id", "obs1"))
121+
KeyValues.of(
122+
KeyValue.of("spring.rabbit.listener.id", "obs1"),
123+
KeyValue.of("messaging.destination.name", "int.observation.testQ1"),
124+
KeyValue.of("messaging.rabbitmq.message.delivery_tag", "1")
125+
)
126+
)
103127
.hasTimerWithNameAndTags("spring.rabbit.listener",
104-
KeyValues.of("spring.rabbit.listener.id", "obs2"));
128+
KeyValues.of(
129+
KeyValue.of("spring.rabbit.listener.id", "obs2"),
130+
KeyValue.of("messaging.destination.name", "int.observation.testQ2"),
131+
KeyValue.of("messaging.rabbitmq.message.delivery_tag", "1")
132+
)
133+
);
105134
};
106135
}
107136

108-
109137
@Configuration
110138
@EnableRabbit
111139
public static class Config {
@@ -159,5 +187,4 @@ void listen2(Message in) {
159187

160188
}
161189

162-
163190
}

0 commit comments

Comments
 (0)