Camel日志的覆写或拦截实现方案咨询
为Apache Camel日志统一添加特定Header值的惯用实现方式
在Apache Camel环境中要让每条日志都带上x-correlation-id这类特定Header值,有几种成熟的惯用方案,根据你的场景可以灵活选择:
方案1:利用MDC(映射诊断上下文)全局注入(最推荐)
MDC是日志框架(Logback/Log4j)提供的线程绑定上下文机制,可以把关联ID这类上下文信息绑定到当前线程,所有日志输出都能自动读取并展示——不仅覆盖Camel的log() DSL和Log组件,连你自己写的业务日志也能生效。
实现步骤:
- 编写MDC处理器:把Exchange中的Header值放入MDC,并在Exchange完成后清理(避免线程复用导致脏数据)
public class CorrelationIdMdcProcessor implements Processor { @Override public void process(Exchange exchange) throws Exception { // 从Header中获取关联ID,没有则设为UNKNOWN String correlationId = exchange.getIn().getHeader("x-correlation-id", "UNKNOWN", String.class); MDC.put("x-correlation-id", correlationId); // 绑定清理逻辑到Exchange生命周期 exchange.addOnCompletion(new SynchronizationAdapter() { @Override public void onComplete(Exchange exchange) { MDC.remove("x-correlation-id"); } }); } }
全局或局部挂载处理器:
- 全局生效:给所有路由添加这个处理器
camelContext.addRoutePolicy(new RoutePolicy() { @Override public void onStart(Route route) { route.getRouteContext().getRoute().getInputs().add(0, new CorrelationIdMdcProcessor()); } }); - 局部生效:在单个路由开头添加
from("direct:order-service") .process(new CorrelationIdMdcProcessor()) .log("Processing order request") .to("jdbc:order-db");
- 全局生效:给所有路由添加这个处理器
修改日志框架配置:在Logback/Log4j的格式中加入MDC字段,比如Logback的
logback.xml:
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %X{x-correlation-id} - %msg%n</pattern> </encoder> </appender>
方案2:自定义LogFormatter扩展Camel Log组件
如果只想针对Camel的log() DSL和Log组件生效,可以自定义LogFormatter,覆盖默认的日志格式逻辑,直接把Header值嵌入日志内容。
实现步骤:
- 继承DefaultLogFormatter并扩展:
public class CorrelationIdLogFormatter extends DefaultLogFormatter { @Override public String format(Exchange exchange, String message) { String correlationId = exchange.getIn().getHeader("x-correlation-id", "UNKNOWN", String.class); // 在原日志内容前拼接关联ID return String.format("[%s] %s", correlationId, super.format(exchange, message)); } }
- 配置使用自定义Formatter:
- 单个log DSL使用:
from("direct:payment-service") .log(LoggingLevel.INFO, new CorrelationIdLogFormatter(), "Processing payment") .to("activemq:payment-queue"); - 全局默认使用:让所有Log组件调用都用这个Formatter
LogComponent logComponent = camelContext.getComponent("log", LogComponent.class); logComponent.setDefaultFormatter(new CorrelationIdLogFormatter());
- 单个log DSL使用:
方案3:使用Intercept策略全局拦截日志端点
通过Camel的interceptSendToEndpoint拦截所有发送到log:*端点的消息,修改日志内容后再转发,适合需要全局修改日志内容的场景。
实现示例:
// 拦截所有log组件的调用 interceptSendToEndpoint("log:*") .process(exchange -> { String correlationId = exchange.getIn().getHeader("x-correlation-id", "UNKNOWN", String.class); // 获取原日志消息并拼接关联ID String originalMsg = exchange.getProperty(LogComponent.LOG_MESSAGE, String.class); if (originalMsg != null) { exchange.setProperty(LogComponent.LOG_MESSAGE, String.format("[%s] %s", correlationId, originalMsg)); } });
注意点:
这个方案需要注意Camel Log组件的消息存储位置(通过LogComponent.LOG_MESSAGE属性获取),如果是带参数的日志(比如.log("Order ID: ${header.orderId}")),需要确保参数解析后再处理。
内容的提问来源于stack exchange,提问作者Darius X.
相关产品推荐
相关产品推荐

