Apache Camel 2.x迁移至3.x/4.x后路由指标兼容性问题求助
兼容Apache Camel 3.x+的路由指标自定义标签实现方案
针对Camel 3.x及以上版本移除MicrometerRoutePolicyNamingStrategy.getTags(Exchange)方法后的自定义标签需求,以下是几个可行的实现方案:
方案一:自定义MicrometerMetricsService扩展指标标签
Camel 3.x+中,MicrometerRoutePolicy依赖MicrometerMetricsService处理指标逻辑,可通过自定义该服务的实现,在记录指标时注入Exchange相关标签:
- 实现自定义
MicrometerMetricsService,重写recordExchangeEvent方法提取所需标签:
public class CustomMicrometerMetricsService extends DefaultMicrometerMetricsService { public CustomMicrometerMetricsService(MeterRegistry meterRegistry, MicrometerRoutePolicyNamingStrategy namingStrategy) { super(meterRegistry, namingStrategy); } @Override public void recordExchangeEvent(Exchange exchange, String eventType, long duration) { // 从Exchange中获取自定义属性 String messageName = exchange.getProperty("messageName", String.class); // 构建自定义标签集合 Tags customTags = Tags.of("messageName", messageName); // 调用父类方法时传入自定义标签 super.recordExchangeEvent(exchange, eventType, duration, customTags); } }
- 在Spring Boot配置中替换默认服务实例:
@Configuration public class CamelMetricsConfig { @Bean public MicrometerMetricsService customMicrometerMetricsService(MeterRegistry meterRegistry, MicrometerRoutePolicyNamingStrategy namingStrategy) { return new CustomMicrometerMetricsService(meterRegistry, namingStrategy); } }
方案二:通过EventNotifier手动上报自定义指标
利用Camel的事件监听机制,监听Exchange完成事件,手动向Micrometer上报带自定义标签的路由指标:
- 实现
EventNotifier监听ExchangeCompletedEvent:
public class CustomExchangeMetricsNotifier extends EventNotifierSupport { private final MeterRegistry meterRegistry; public CustomExchangeMetricsNotifier(MeterRegistry meterRegistry) { this.meterRegistry = meterRegistry; } @Override public void notify(EventObject event) throws Exception { if (event instanceof ExchangeCompletedEvent) { ExchangeCompletedEvent completedEvent = (ExchangeCompletedEvent) event; Exchange exchange = completedEvent.getExchange(); Route route = exchange.getUnitOfWork().getRouteContext().getRoute(); // 提取自定义标签和指标数据 String routeId = route.getId(); String messageName = exchange.getProperty("messageName", String.class); long duration = exchange.getDuration(); // 上报路由耗时指标 Timer.builder("camel.route.exchange.duration") .tags("routeId", routeId, "messageName", messageName) .register(meterRegistry) .record(duration, TimeUnit.MILLISECONDS); // 按需上报成功/失败计数 if (exchange.isFailed()) { Counter.builder("camel.route.exchange.failed") .tags("routeId", routeId, "messageName", messageName) .register(meterRegistry) .increment(); } else { Counter.builder("camel.route.exchange.success") .tags("routeId", routeId, "messageName", messageName) .register(meterRegistry) .increment(); } } } @Override public boolean isEnabled(EventObject event) { return event instanceof ExchangeCompletedEvent; } }
- 注册该
EventNotifier到Camel上下文:
@Configuration public class CamelEventConfig { @Bean public EventNotifier customExchangeMetricsNotifier(MeterRegistry meterRegistry) { return new CustomExchangeMetricsNotifier(meterRegistry); } }
方案三:结合ThreadLocal与MeterFilter注入动态标签
通过ThreadLocal暂存Exchange的自定义属性,再利用Micrometer的MeterFilter全局添加标签:
- 创建ThreadLocal工具类暂存属性:
public class ExchangeTagContext { private static final ThreadLocal<String> MESSAGE_NAME = new ThreadLocal<>(); public static void setMessageName(String messageName) { MESSAGE_NAME.set(messageName); } public static String getMessageName() { return MESSAGE_NAME.get(); } public static void clear() { MESSAGE_NAME.remove(); } }
- 在路由中添加Processor存入并清理ThreadLocal:
from("direct:start") .process(exchange -> { String messageName = exchange.getProperty("messageName", String.class); ExchangeTagContext.setMessageName(messageName); }) // 后续路由逻辑 .to("mock:end") .process(exchange -> ExchangeTagContext.clear()); // 避免内存泄漏
- 自定义
MeterFilter为Camel路由指标添加标签:
public class CamelRouteTagFilter implements MeterFilter { @Override public Meter.Id map(Meter.Id id) { // 仅对Camel路由相关指标添加标签 if (id.getName().startsWith("camel.route.")) { String messageName = ExchangeTagContext.getMessageName(); if (messageName != null) { return id.withTag("messageName", messageName); } } return id; } }
- 注册MeterFilter到Spring Boot:
@Configuration public class MicrometerConfig { @Bean public MeterFilter camelRouteTagFilter() { return new CamelRouteTagFilter(); } }
内容的提问来源于stack exchange,提问作者Walron
相关产品推荐
相关产品推荐

