英文:
How to get metrics for RabbitMQ exchanges with Spring Boot?
问题
Spring Boot自动(通过actuator)为队列(spring_rabbitmq_listener*
)提供指标。
是否有一种方法可以获取服务发送到的交换机的类似指标?
该应用程序正在使用
org.springframework.boot:spring-boot-starter-actuator
org.springframework.boot:spring-boot-starter-amqp
org.springframework.boot:spring-boot-starter-web
全部版本为3.1.0
我尝试过 rabbitTemplate.setObservationEnabled(true);
但没有帮助。
英文:
Spring Boot automagically (with the actuator) provides metrics for queues (spring_rabbitmq_listener*
).
Is there a way to get similar metrics for the exchanges a services sends to?
The application is using
org.springframework.boot:spring-boot-starter-actuator
org.springframework.boot:spring-boot-starter-amqp
org.springframework.boot:spring-boot-starter-web
all in 3.1.0
I've tried rabbitTemplate.setObservationEnabled(true);
but that doesn't help.
答案1
得分: 1
与监听容器不同,用于向交换机发送消息的RabbitTemplate
不支持经典的Micrometer计时器。
然而,从版本3.0开始,您可以启用Micrometer的Observation功能,该功能包括Micrometer指标(以及添加跟踪功能)。
请注意,如果您为监听容器启用观察功能,将禁用默认指标(因为同时维护两者没有意义)。观察指标具有稍微不同的标签。
链接:https://docs.spring.io/spring-amqp/docs/current/reference/html/#micrometer-observation
从版本3.0开始,RabbitTemplate和监听容器现在支持使用Micrometer进行观察。
设置每个组件的
observationEnabled
以启用观察;这将禁用Micrometer计时器,因为计时器现在将由每个观察管理。在使用注释监听器时,请在容器工厂上设置observationEnabled
。
编辑:
这对我来说很有效:
@SpringBootApplication
public class So76530102Application {
public static void main(String[] args) {
SpringApplication.run(So76530102Application.class, args).close();
}
@Bean
ApplicationRunner runner(RabbitTemplate template, MeterRegistry registry) {
template.setObservationEnabled(true);
return args -> {
template.convertAndSend("foo", "bar", "test");
Timer timer = registry.get("spring.rabbit.template")
.tagKeys("spring.rabbit.template.name", "error")
.timer();
System.out.println(timer.count());
};
}
}
1
然而,计时器不包含有关交换机或路由键的任何信息(跟踪数据具有exchange/rk
形式的信息)。
编辑2:
如果您想将交换机/路由键作为标签添加到计量器...
@SpringBootApplication
public class So76530102Application {
public static void main(String[] args) {
SpringApplication.run(So76530102Application.class, args).close();
}
@Bean
ApplicationRunner runner(RabbitTemplate template, MeterRegistry registry) {
template.setObservationEnabled(true);
template.setObservationConvention(new MyConvention());
return args -> {
template.convertAndSend("foo", "bar", "test");
registry.getMeters().stream()
.filter(m -> m.getId().getName().equals("spring.rabbit.template"))
.forEach(m -> System.out.println(m.getId()));
Timer timer = registry.get("spring.rabbit.template")
.tagKeys("spring.rabbit.template.name", "error")
.tag("dest", "foo/bar")
.timer();
System.out.println(timer.count());
};
}
}
class MyConvention extends DefaultRabbitTemplateObservationConvention {
@Override
public KeyValues getLowCardinalityKeyValues(RabbitMessageSenderContext context) {
return super.getLowCardinalityKeyValues(context).and("dest", context.getDestination());
}
}
MeterId{name='spring.rabbit.template', tags=[tag(dest=foo/bar),tag(error=none),tag(spring.rabbit.template.name=rabbitTemplate)]}
1
英文:
Unlike the listener containers, the RabbitTemplate
(used to send messages to exchanges) does not support classic Micrometer Timers.
However, starting with version 3.0, you can enable Observation by Micrometer which does include Micrometer metrics (as well as adding tracing capabilities).
Note that if you enable observation for the listener containers, the default metrics are disabled (because it doesn't make sense to maintain both). The observation metrics have slightly different tags.
https://docs.spring.io/spring-amqp/docs/current/reference/html/#micrometer-observation
>Using Micrometer for observation is now supported, since version 3.0, for the RabbitTemplate and listener containers.
>Set observationEnabled
on each component to enable observation; this will disable Micrometer Timers because the timers will now be managed with each observation. When using annotated listeners, set observationEnabled
on the container factory.
EDIT
This works fine for me:
@SpringBootApplication
public class So76530102Application {
public static void main(String[] args) {
SpringApplication.run(So76530102Application.class, args).close();
}
@Bean
ApplicationRunner runner(RabbitTemplate template, MeterRegistry registry) {
template.setObservationEnabled(true);
return args -> {
template.convertAndSend("foo", "bar", "test");
Timer timer = registry.get("spring.rabbit.template")
.tagKeys("spring.rabbit.template.name", "error")
.timer();
System.out.println(timer.count());
};
}
}
1
However, the timer does not contain any information about the exchange or routing key (the trace data does have that information with the form exchange/rk
).
EDIT2
If you want to add the exhange/rk as a tag to the meter...
@SpringBootApplication
public class So76530102Application {
public static void main(String[] args) {
SpringApplication.run(So76530102Application.class, args).close();
}
@Bean
ApplicationRunner runner(RabbitTemplate template, MeterRegistry registry) {
template.setObservationEnabled(true);
template.setObservationConvention(new MyConvention());
return args -> {
template.convertAndSend("foo", "bar", "test");
registry.getMeters().stream()
.filter(m -> m.getId().getName().equals("spring.rabbit.template"))
.forEach(m -> System.out.println(m.getId()));
Timer timer = registry.get("spring.rabbit.template")
.tagKeys("spring.rabbit.template.name", "error")
.tag("dest", "foo/bar")
.timer();
System.out.println(timer.count());
};
}
}
class MyConvention extends DefaultRabbitTemplateObservationConvention {
@Override
public KeyValues getLowCardinalityKeyValues(RabbitMessageSenderContext context) {
return super.getLowCardinalityKeyValues(context).and("dest", context.getDestination());
}
}
MeterId{name='spring.rabbit.template', tags=[tag(dest=foo/bar),tag(error=none),tag(spring.rabbit.template.name=rabbitTemplate)]}
1
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论