[英]How to access incoming HTTP requests in X-Ray SegmentListener?
I use AWS X-Ray SDK for Java to enable X-Ray tracing for my Spring Boot micro services.我对 Java 使用AWS X-Ray SDK来为我的 Spring Boot 微服务启用 X-Ray 跟踪。 With following snippet I am able to attach a custom SegmentListener
:通过以下代码片段,我可以附加自定义SegmentListener
:
final AWSXRayRecorder recorder = AWSXRayRecorderBuilder
.standard()
.withPlugin(new EcsPlugin())
.withSegmentListener(new SLF4JSegmentListener())
.withSegmentListener(new MyHttpHeaderSegementListener())
.build();
AWSXRay.setGlobalRecorder(recorder);
In MyHttpHeaderSegementListener
I try to inject a X-Ray annotation based on an incoming HTTP request header (from the frontend):在MyHttpHeaderSegementListener
,我尝试根据传入的 HTTP 请求 header(来自前端)注入 X-Ray 注释:
public class MyHttpHeaderSegementListener implements SegmentListener {
// snippet source: https://stackoverflow.com/a/54349178/6489012
public static Optional<HttpServletRequest> getCurrentHttpRequest() {
return Optional.ofNullable(RequestContextHolder.getRequestAttributes())
.filter(ServletRequestAttributes.class::isInstance)
.map(ServletRequestAttributes.class::cast)
.map(ServletRequestAttributes::getRequest);
}
public MyHttpHeaderSegementListener() {}
@Override
public void onBeginSegment(final Segment segment) {
final var httpContext = MyHttpHeaderSegementListener.getCurrentHttpRequest();
httpContext.ifPresent(context -> segment.putAnnotation("Origin", context.getHeader("Origin")));
}
}
The segment listener is triggered as expected onBeginSegment
segment but MyHttpHeaderSegementListener.getCurrentHttpRequest()
always returns an Optional.empty
.段侦听器按预期触发onBeginSegment
段,但MyHttpHeaderSegementListener.getCurrentHttpRequest()
始终返回Optional.empty
。
Controller
) within a SegmentListener
?是否有可能在SegmentListener
中检查传入的 HTTP 请求(因为它们是由Controller
接收的)?aws-xray-sdk-java
maybe even support a native way to do so? aws-xray-sdk-java
甚至可能支持原生方式吗?RequestContextHolder
always empty?为什么从RequestContextHolder
中取出来的请求总是空的?(A bit off-topic but: 4. Is it even a good practice to set an annotation based on a HTTP header) (有点题外话,但是:4.根据 HTTP 标头设置注释甚至是一个好习惯)
I have no answer for the 2. and 3. question but I found an answer for 1. question.我对 2. 和 3. 问题没有答案,但我找到了 1. 问题的答案。
For incoming requests you need to add a Spring Filter to configure AWS X-Ray .对于传入请求,您需要添加一个 Spring 过滤器来配置 AWS X-Ray 。 As filters have access to the HTTP request I just wrapped my own filter around the com.amazonaws.xray.javax.servlet.AWSXRayServletFilter
of AWS:由于过滤器可以访问 HTTP 请求,我只是将自己的过滤器包装在 AWS 的com.amazonaws.xray.javax.servlet.AWSXRayServletFilter
周围:
public class XRayServletFilter extends AWSXRayServletFilter {
public XRayServletFilter(String fixedSegmentName) {
super(fixedSegmentName);
}
@Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
this.addHttpRequestToContext(request);
super.doFilter(request, response, chain);
}
private void addHttpRequestToContext(final ServletRequest request){
final Optional<HttpServletRequest> httpServletRequest = HttpRequestUtils.castToHttpRequest(request);
if (httpServletRequest.isPresent()) {
final ServletRequestAttributes requestAttributes = new ServletRequestAttributes(httpServletRequest.get());
RequestContextHolder.setRequestAttributes(requestAttributes);
}
}
}
Which uses a static class that I wrote:其中使用了我写的 static class:
public final class HttpRequestUtils {
public static Optional<HttpServletRequest> getCurrentHttpRequest() {
return Optional.ofNullable(RequestContextHolder.getRequestAttributes())
.filter(ServletRequestAttributes.class::isInstance)
.map(ServletRequestAttributes.class::cast)
.map(ServletRequestAttributes::getRequest);
}
public static Optional<HttpServletRequest> castToHttpRequest(ServletRequest request) {
try {
return Optional.of((HttpServletRequest) request);
} catch (ClassCastException classCastException) {
return Optional.empty();
}
}
}
This custom filter basically sets the HTTP requests in the RequestContextHolder
.这个自定义过滤器基本上在 RequestContextHolder 中设置了RequestContextHolder
请求。 After that you can use it in your segment listeners:之后,您可以在您的分段侦听器中使用它:
public class MyHttpHeaderSegementListener implements SegmentListener {
public MyHttpHeaderSegementListener() {}
@Override
public void onBeginSegment(final Segment segment) {
final Optional<HttpServletRequest> request = HttpRequestUtils.getCurrentHttpRequest();
request.map(req -> req.getHeader("Origin")).ifPresent(origin -> segment.putAnnotation("client_origin", origin));;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.