簡體   English   中英

在 spring 配置文件中進行 HTTP 調用后,spring 集成應用程序中的日志中缺少相關性

[英]Missing correlationId in logs in spring integration application after a HTTP call made in spring configuration file

在其中一個 spring 集成應用程序中,我嘗試使用 log4j 和 MDC 在日志中打印correlationId(我將在標題中將其作為“x-correlation-id”=“postman”)打印。 請找到下面的spring web過濾器來攔截傳入的請求頭,通過整個事務將它們打印在日志中

 import org.slf4j.MDC; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.UUID; import static org.apache.logging.log4j.util.Strings.isBlank; @Component public class CorrelationIDFilter extends OncePerRequestFilter { private static final String CORRELATION_ID_HEADER_NAME = "x-correlation-id"; private static final String CORRELATION_ID_LOG_VAR_NAME = "correlationId"; @Override protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { try { final String correlationId = getCorrelationIdFromHeader(httpServletRequest); MDC.put(CORRELATION_ID_LOG_VAR_NAME, correlationId); filterChain.doFilter(httpServletRequest, httpServletResponse); } finally { MDC.remove(CORRELATION_ID_LOG_VAR_NAME); } } private String getCorrelationIdFromHeader(final HttpServletRequest httpServletRequest) { String correlationId = httpServletRequest.getHeader(CORRELATION_ID_HEADER_NAME); if (isBlank(correlationId)) { correlationId = generateUniqueCorrelationId(); } logger.info("correlationId :: " + correlationId); return correlationId; } private String generateUniqueCorrelationId() { return UUID.randomUUID().toString(); } @Override public void destroy() { MDC.remove(CORRELATION_ID_LOG_VAR_NAME); } }

spring-integration.xml

 <int:annotation-config/> <context:component-scan base-package="com.springintegration" /> <!-- Gateway --> <int-http:inbound-gateway id="lpaGateway" request-channel="inboundGatewayRequests" supported-methods="POST" path="/api/v1/mdc" request-payload-type="java.lang.String" reply-timeout="300000" reply-channel="outboundGatewayResponses" error-channel="httpErrorChannel"> <int-http:request-mapping consumes="application/xml" produces="application/xml" /> </int-http:inbound-gateway> <int:transformer input-channel="inboundGatewayRequests" ref="springIntegrationMdcTransformer" method="buildRequestPayload" output-channel="httpPostRequests" /> <beans:bean id="headerMapper" class="org.springframework.integration.http.support.DefaultHttpHeaderMapper"> <beans:property name="outboundHeaderNames" value="HTTP_REQUEST_HEADERS, Content-Type, Authorization" /> </beans:bean> <!-- HTTP POST --> <int:chain input-channel="httpPostRequests" output-channel="httpPostRsponses"> <int:header-enricher> <int:header name="Content-Type" value="application/xml" /> <int:header name="Authorization" expression="payload.getoAuthBean().getAccessToken()" /> </int:header-enricher> <int:transformer expression="payload.getLpaRequest()" /> <int-http:outbound-gateway id="lpaPostGateway" url="${post_endpoint}" http-method="POST" extract-request-payload="true" expected-response-type="java.lang.String" header-mapper="headerMapper"> </int-http:outbound-gateway> </int:chain> <int:transformer input-channel="httpPostRsponses" ref="springIntegrationMdcTransformer" method="examinePostResponse" output-channel="getDelayer" /> <!-- Wait till polling frequency (in milliseconds) is met before invoking HTTP GET --> <int:delayer id="delayer" input-channel="getDelayer" default-delay="0" expression="payload.getPollingFrequency()" output-channel="httpGetRequests" /> <!-- HTTP GET --> <int:chain input-channel="httpGetRequests" output-channel="httpGetResponses"> <int:header-enricher> <int:header name="Content-Type" value="application/xml" /> <int:header name="Authorization" expression="payload.getoAuthBean().getAccessToken()" /> </int:header-enricher> <int-http:outbound-gateway id="httpGetGateway" url-expression='"${get_endpoint}".concat("/").concat(payload.getReferenceID())' http-method="GET" expected-response-type="java.lang.String" header-mapper="headerMapper"> </int-http:outbound-gateway> </int:chain> <!-- Examine LPA HTTP GET response --> <int:transformer input-channel="httpGetResponses" ref="springIntegrationMdcTransformer" method="examineGetResponse" output-channel="outboundGatewayResponses" />

log4j2.xml

 <Configuration status="WARN"> <Properties> <Property name="CONVERSION_PATTERN">%sn %d{yyyy/MM/dd HH:mm:ss,SSS} %r [%-6p] [%t] [%X{correlationId}] %c{3} %C{3}.%M(%F:%L) – %m%n</Property> </Properties> <Loggers> <Root level="info}"> <AppenderRef ref="SERVICE_ALL_FILE_APPENDER" /> </Root> <Logger name="SERVICE_LOGGER" level="info" additivity="false"> <AppenderRef ref="SERVICE_FILE_APPENDER" /> </Logger> </Loggers> <Appenders> <Console name="CONSOLE_APPENDER" target="SYSTEM_OUT"> <PatternLayout pattern="${CONVERSION_PATTERN}" /> </Console> <RollingFile name="SERVICE_FILE_APPENDER" fileName="/logs/service_log.log" filePattern="/logs/service_log-%d{yyyy-MM-dd}-%i.log"> <PatternLayout pattern="${CONVERSION_PATTERN}" /> </RollingFile> </Appenders> </Configuration>

變壓器類

 @Component("springIntegrationMdcTransformer") public class SpringIntegrationMDCTransformer { private static final Logger logger = getLogger("SERVICE_LOGGER"); public Message < Object > buildRequestPayload(Message < String > inputRequest) { logger.info("buildRequestPayload"); logger.info(MDC.getCopyOfContextMap()); return withPayload((Object) inputRequest.getPayload()) .copyHeadersIfAbsent(inputRequest.getHeaders()) .build(); } public Message < Object > examinePostResponse(Message < Object > channelMessage) { logger.info("examinePostResponse"); logger.info(MDC.getCopyOfContextMap()); return withPayload(channelMessage.getPayload()) .copyHeadersIfAbsent(channelMessage.getHeaders()) .build(); } public Message < Object > examineGetResponse(Message < Object > channelMessage) { logger.info("examineGetResponse"); logger.info(MDC.getCopyOfContextMap()); return withPayload(channelMessage.getPayload()) .copyHeadersIfAbsent(channelMessage.getHeaders()) .build(); }

這就是我看到日志的方式。 我從 spring 配置文件中看到第二次 HTTP 調用后,我在日志語句中丟失了correlationId。 我添加了日志語句來在每個通道執行后打印 MDC contextMap。 請幫助我理解為什么會發生這種情況以及為此推薦的解決方案。

 915 2021/10/24 03:05:29,794 242390 [INFO ] [http-nio-8080-exec-3] [postman] SERVICE_LOGGER springintegrationmdc.transformer.buildRequestPayload(SpringIntegrationMDCTransformer.java:18) – buildRequestPayload 917 2021/10/24 03:05:30,627 243223 [INFO ] [http-nio-8080-exec-3] [postman] SERVICE_LOGGER core.service.SpringIntegrationMDCTransformer.checkCache(SpringIntegrationMDCTransformer.java:19) – {correlationId=postman} 916 2021/10/24 03:05:29,802 242398 [INFO ] [http-nio-8080-exec-3] [postman] SERVICE_LOGGER core.service.SpringIntegrationMDCTransformer.checkCache(SpringIntegrationMDCTransformer.java:26) – examinePostResponse 917 2021/10/24 03:05:30,627 243223 [INFO ] [http-nio-8080-exec-3] [postman] SERVICE_LOGGER core.service.SpringIntegrationMDCTransformer.checkCache(SpringIntegrationMDCTransformer.java:27) – {correlationId=postman} 992 2021/10/24 03:05:58,911 271507 [INFO ] [task-scheduler-1] [] SERVICE_LOGGER core.transformer.LPATransformer.examineLPAGetResponse(SpringIntegrationMDCTransformer.java:34) – examineGetResponse 993 2021/10/24 03:05:59,954 272550 [INFO ] [task-scheduler-1] [] SERVICE_LOGGER core.transformer.LPATransformer.examineLPAGetResponse(SpringIntegrationMDCTransformer.java:35) – {}

MDC是線程綁定的。 您絕對無法在另一個線程中看到它的狀態。 仔細查看您的日志:

916 2021/10/24 03:05:29,802 242398 [INFO  ] [http-nio-8080-exec-3] [postman] SERVICE_LOGGER core.service.SpringIntegrationMDCTransformer.checkCache(SpringIntegrationMDCTransformer.java:26) – examinePostResponse
917 2021/10/24 03:05:30,627 243223 [INFO  ] [http-nio-8080-exec-3] [postman] SERVICE_LOGGER core.service.SpringIntegrationMDCTransformer.checkCache(SpringIntegrationMDCTransformer.java:27) – {correlationId=postman}
992 2021/10/24 03:05:58,911 271507 [INFO  ] [task-scheduler-1] [] SERVICE_LOGGER core.transformer.LPATransformer.examineLPAGetResponse(SpringIntegrationMDCTransformer.java:34) – examineGetResponse

http-nio-8080-exec-3task-scheduler-1 因此,您確實使用了不同的、未連接的線程。 因此,您會在http-nio-8080-exec-3看到MDC內容,它是CorrelationIDFilter的一部分,但在httpGetRequests通道子流httpGetRequests不到它,因為在預定延遲后,該內容已在不同線程中啟動.

或者不要使用delayer ,或者考慮實現線程狀態傳輸功能。 請參閱ThreadStatePropagationChannelInterceptor及其安全傳播實現: https : //docs.spring.io/spring-integration/docs/current/reference/html/security.html#security-context-propagation

另一種方法是將您的關聯 ID 存儲到消息標題中,並在您打印日志時從那里獲取它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM