Sleuth tracer.currentSpan() 在 WebFlux WebFilter 中显示为空
Sleuth tracer.currentSpan() coming as empty in WebFlux WebFilter
如何在反应式 WebFlux 上下文中的响应 headers 中添加跟踪 ID?我尝试使用以下代码,但跨度始终为空。 Sleuth 依赖版本为 3.0.3,Spring 引导版本为 2.5.4
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
@Component
public class GatewaySleuthFilter implements WebFilter {
@Autowired
Tracer tracer;
@Override
public Mono<Void> filter(ServerWebExchange exchange,
WebFilterChain chain) {
ServerHttpResponse response = exchange.getResponse();
response.beforeCommit(() -> {
Span span = tracer.currentSpan();
if (span != null) {
exchange.getResponse().getHeaders().add("trace-id", span.context().traceId());
exchange.getResponse().getHeaders().add("span-id", span.context().spanId());
}
return Mono.empty();
});
return chain.filter(exchange);
}
}
使用 WebFilter
是正确的方法,docs suggest something similar.
我不确定你为什么会得到这种行为(我猜 beforeCommit
可能不在上下文中),这是文档的建议,我会先尝试这个:
@Bean
WebFilter traceIdInResponseFilter(Tracer tracer) {
return (exchange, chain) -> {
Span span = tracer.currentSpan();
if (span != null) {
exchange.getResponse().getHeaders().add("trace-id", span.context().traceId());
exchange.getResponse().getHeaders().add("span-id", span.context().spanId());
}
return chain.filter(exchange);
};
}
以下是一些其他问题排查指南:
- 请检查您的跨度是否被采样
- 请检查 Span 是否已创建并且您是否在它的上下文中
- 你能检查一下其他 instrumentation style 是否有效吗(我推荐
DECORATE_QUEUES
)?
当前跨度是 null
,因为网关中的默认检测选项是手动的。因此,您负责检索跨度。所以你有两个选择。
选项 1 是使用 WebFluxSleuthOperators
从 ServerWebExchange
(https://github.com/spring-cloud/spring-cloud-sleuth/blob/v3.0.4/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/web/WebFluxSleuthOperators.java) 中检索当前跟踪上下文,如下所示:
@Bean
WebFilter traceIdInResponseFilter() {
return (exchange, chain) -> {
Span span =
WebFluxSleuthOperators.currentTraceContext(exchange);
if (span != null) {
exchange.getResponse().getHeaders().add("trace-id", span.context().traceId());
exchange.getResponse().getHeaders().add("span-id", span.context().spanId());
}
return chain.filter(exchange);
};
}
或选项 2 与 Jontan 提到的不同的 Sleuth Reactor 集成 https://docs.spring.io/spring-cloud-sleuth/docs/current/reference/htmlsingle/#sleuth-reactor-integration 如下:
spring:
sleuth:
reactor:
# try decorate_queues and if that fails decorate_on_each
# decorate_on_each can lead to dramatic performance degradation
instrumentation-type: decorate_queues
下面的代码对我有用。
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
ServerHttpResponse response = exchange.getResponse();
response.beforeCommit(() -> {
Span span = exchange.getAttribute(Span.class.getName());
if (span != null) {
exchange.getResponse().getHeaders().add(TRACE_ID_HEADER, span.context().traceId());
exchange.getResponse().getHeaders().add(SPAN_ID_HEADER, span.context().spanId());
}
return Mono.empty();
});
return chain.filter(exchange);
}
如何在反应式 WebFlux 上下文中的响应 headers 中添加跟踪 ID?我尝试使用以下代码,但跨度始终为空。 Sleuth 依赖版本为 3.0.3,Spring 引导版本为 2.5.4
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
@Component
public class GatewaySleuthFilter implements WebFilter {
@Autowired
Tracer tracer;
@Override
public Mono<Void> filter(ServerWebExchange exchange,
WebFilterChain chain) {
ServerHttpResponse response = exchange.getResponse();
response.beforeCommit(() -> {
Span span = tracer.currentSpan();
if (span != null) {
exchange.getResponse().getHeaders().add("trace-id", span.context().traceId());
exchange.getResponse().getHeaders().add("span-id", span.context().spanId());
}
return Mono.empty();
});
return chain.filter(exchange);
}
}
使用 WebFilter
是正确的方法,docs suggest something similar.
我不确定你为什么会得到这种行为(我猜 beforeCommit
可能不在上下文中),这是文档的建议,我会先尝试这个:
@Bean
WebFilter traceIdInResponseFilter(Tracer tracer) {
return (exchange, chain) -> {
Span span = tracer.currentSpan();
if (span != null) {
exchange.getResponse().getHeaders().add("trace-id", span.context().traceId());
exchange.getResponse().getHeaders().add("span-id", span.context().spanId());
}
return chain.filter(exchange);
};
}
以下是一些其他问题排查指南:
- 请检查您的跨度是否被采样
- 请检查 Span 是否已创建并且您是否在它的上下文中
- 你能检查一下其他 instrumentation style 是否有效吗(我推荐
DECORATE_QUEUES
)?
当前跨度是 null
,因为网关中的默认检测选项是手动的。因此,您负责检索跨度。所以你有两个选择。
选项 1 是使用 WebFluxSleuthOperators
从 ServerWebExchange
(https://github.com/spring-cloud/spring-cloud-sleuth/blob/v3.0.4/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/web/WebFluxSleuthOperators.java) 中检索当前跟踪上下文,如下所示:
@Bean
WebFilter traceIdInResponseFilter() {
return (exchange, chain) -> {
Span span =
WebFluxSleuthOperators.currentTraceContext(exchange);
if (span != null) {
exchange.getResponse().getHeaders().add("trace-id", span.context().traceId());
exchange.getResponse().getHeaders().add("span-id", span.context().spanId());
}
return chain.filter(exchange);
};
}
或选项 2 与 Jontan 提到的不同的 Sleuth Reactor 集成 https://docs.spring.io/spring-cloud-sleuth/docs/current/reference/htmlsingle/#sleuth-reactor-integration 如下:
spring:
sleuth:
reactor:
# try decorate_queues and if that fails decorate_on_each
# decorate_on_each can lead to dramatic performance degradation
instrumentation-type: decorate_queues
下面的代码对我有用。
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
ServerHttpResponse response = exchange.getResponse();
response.beforeCommit(() -> {
Span span = exchange.getAttribute(Span.class.getName());
if (span != null) {
exchange.getResponse().getHeaders().add(TRACE_ID_HEADER, span.context().traceId());
exchange.getResponse().getHeaders().add(SPAN_ID_HEADER, span.context().spanId());
}
return Mono.empty();
});
return chain.filter(exchange);
}