| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
|
Please update the Spring Gateway cases, UT is not enough to verify plugins codes. There are many test scenarios here, such as this is for 3.x GW. If you don't know how to run this, please follow Plugin automatic test framework docs. You could change codes of those cases, and verify them locally with new expectation files. |
Sorry, something went wrong.
|
You can see, your new codes break gateway-3.x-filter-context-scenario. That is another thing you should fix about the test scenarios. |
Sorry, something went wrong.
Sure, I'll take a look at the documentation you provided first. |
Sorry, something went wrong.
|
I think the issue seems to be repetitive with this #539 , and we can support it in this way. @Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain){
// fetch trace ID
String traceId = WebFluxSkyWalkingTraceContext.traceId(exchange);
// fetch segment ID
String segmentId = WebFluxSkyWalkingTraceContext.segmentId(exchange);
// fetch span ID
int spanId = WebFluxSkyWalkingTraceContext.spanId(exchange);
return chain.filter(exchange);
}
|
Sorry, something went wrong.
|
@yqw570994511 Could you verify this new way? If it works, we don't need extra filter interceptor. |
Sorry, something went wrong.
Thank you, I'll try this way |
Sorry, something went wrong.
Thank you, I'll try this way |
Sorry, something went wrong.
I tried it according to the method you gave, and it achieved the same effect as my previous code:
I got the following result:
But when I am in another situation, it can't meet my needs.
The result of using the new solution is as follows:
I think the new scheme can support more scenarios and should help many people like me who have similar needs. |
Sorry, something went wrong.
|
If this targets to support custom filters, I think it makes sense. |
Sorry, something went wrong.
Sorry, something went wrong.
|
The problem I found is that when the gateway forwards to downstream web services, the traceId changes and the entire process is not linked together |
Sorry, something went wrong.
|
Why ping me? |
Sorry, something went wrong.
The tid of the log printed in the spring gateway interceptor is inconsistent with the tid of the log printed in the downstream service interceptor after forwarding. Is there any way to troubleshoot? |
Sorry, something went wrong.
|
I am not following. How to debug Agent and plugins are common knowledge. |
Sorry, something went wrong.
|
Here is a pull request discussion. Please don't mix things here. |
Sorry, something went wrong.
…e_support_gateway_filter_trace_id
…race_id' into feature_support_gateway_filter_trace_id
|
It is good to see tests are passed. Thanks. One question about this doc, with your new plugin gets merged, does user still need to add manual codes? Which scenarios are automatically working, which are still not? |
Sorry, something went wrong.
| STACK_DEEP.get().getAndIncrement(); | ||
| if (isEntry()) { |
There was a problem hiding this comment.
I think you have some duplicate executions here and same as isExit.
STACK_DEEP.get().getAndIncrement() will return 0 for the first time(as Entry), and STACK_DEEP.get().decrementAndGet() will return 0 too for the last time(as Exit).
Your codes call getThreadLocal and getIntValue twice. You could polish codes about this.
Sorry, something went wrong.
There was a problem hiding this comment.
@yqw570994511 Could you check this and polish?
Sorry, something went wrong.
There was a problem hiding this comment.
@yqw570994511 Could you check this and polish?
Thank you, I will adjust my code as follows
public class GatewayFilterInterceptor implements InstanceMethodsAroundInterceptor {
private static final ThreadLocal<AtomicInteger> STACK_DEEP = ThreadLocal.withInitial(() -> new AtomicInteger(0));
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
if (isEntry()) {
ServerWebExchange exchange = (ServerWebExchange) allArguments[0];
EnhancedInstance enhancedInstance = getInstance(exchange);
AbstractSpan span = ContextManager.createLocalSpan("SpringCloudGateway/GatewayFilter");
if (enhancedInstance != null && enhancedInstance.getSkyWalkingDynamicField() != null) {
ContextManager.continued((ContextSnapshot) enhancedInstance.getSkyWalkingDynamicField());
}
span.setComponent(SPRING_CLOUD_GATEWAY);
}
}
public static EnhancedInstance getInstance(Object o) {
EnhancedInstance instance = null;
if (o instanceof DefaultServerWebExchange) {
instance = (EnhancedInstance) o;
} else if (o instanceof ServerWebExchangeDecorator) {
ServerWebExchange delegate = ((ServerWebExchangeDecorator) o).getDelegate();
return getInstance(delegate);
}
return instance;
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
if (isExit()) {
if (ContextManager.isActive()) {
ContextManager.stopSpan();
}
}
return ret;
}
@Override
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t) {
ContextManager.activeSpan().log(t);
}
private boolean isEntry() {
return STACK_DEEP.get().getAndIncrement() == 0;
}
private boolean isExit() {
boolean isExit = STACK_DEEP.get().decrementAndGet() == 0;
if (isExit) {
STACK_DEEP.remove();
}
return isExit;
}
}
If you think it is feasible, can I submit the code accordingly?
Sorry, something went wrong.
There was a problem hiding this comment.
Yes, please go ahead
Sorry, something went wrong.
|
I tried it according to the method you gave, and it achieved the same effect as my previous code @Component
public class Filter1 implements GlobalFilter, Ordered {
private static final Logger log = LoggerFactory.getLogger(Filter1.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// fetch trace ID
String traceId = WebFluxSkyWalkingTraceContext.traceId(exchange);
// fetch segment ID
String segmentId = WebFluxSkyWalkingTraceContext.segmentId(exchange);
// fetch span ID
int spanId = WebFluxSkyWalkingTraceContext.spanId(exchange);
log.info("filter1 traceId: {}, segmentId: {}, spanId: {}", traceId, segmentId, spanId);
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -100;
}
}
I got the following result
But when I am in another situation, it can't meet my needs. My project is configured with logback to output skywalking's traceId to help me track problems, but using the above method, I can see that skywalking's traceId is not output. In the production environment, I really need my log to print out the traceId, and I also hope that I can achieve this goal by writing business code as much as possible. For example, I hope my filter code can output the traceId in the log like this: @Component
public class Filter1 implements GlobalFilter, Ordered {
private static final Logger log = LoggerFactory.getLogger(Filter1.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("filter1 running");
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -100;
}
}
The result of using the new solution is as follows: I think the new scheme can support more scenarios and should help many people like me who have similar needs
I tried it according to the method you gave, and it achieved the same effect as my previous code I got the following result
But when I am in another situation, it can't meet my needs. My project is configured with logback to output skywalking's traceId to help me track problems, but using the above method, I can see that skywalking's traceId is not output. In the production environment, I really need my log to print out the traceId, and I also hope that I can achieve this goal by writing business code as much as possible. For example, I hope my filter code can output the traceId in the log like this: @Component public class Filter1 implements GlobalFilter, Ordered { private static final Logger log = LoggerFactory.getLogger(Filter1.class); @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { log.info("filter1 running"); return chain.filter(exchange); } @Override public int getOrder() { return -100; } } The result of using the new solution is as follows: I think the new scheme can support more scenarios and should help many people like me who have similar needs
Writing code similar to this is enough: private static final Logger log = LoggerFactory.getLogger(Filter1.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("filter1 running");
// fetch trace ID
String traceId = TraceContext.traceId();
log.info("filter1 traceId: {}", traceId);
// fetch segment ID
String segmentId = TraceContext.segmentId();
log.info("filter1 segmentId: {}", segmentId);
// fetch span ID
int spanId = TraceContext.spanId();
log.info("filter1 spanId: {}", spanId);
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -100;
}
} private static final Logger log = LoggerFactory.getLogger(GatewayFilter1.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("gatewayFilter1 running");
return chain.filter(exchange);
}
|
Sorry, something went wrong.
|
Could you reformat your comment? It is a little chaos from reading. I tried to edit but still not clear. |
Sorry, something went wrong.
|
The reason I am asking about, is not doubting your PR. The key is, I want to set up a good boundary for community users. |
Sorry, something went wrong.
|
Because in this doc, it mentioned about fetching trace IDs, I had known they are not able to output in the same place of the logs. We don't need to talk about that part. The question is, are all filters logs carrying logs automatically now? Or some fliters can, others can't. If it is later, then which filters still can't have the automatic injected trace contexts in their logs. |
Sorry, something went wrong.
Writing code similar to this is enough: @Component
public class Filter1 implements GlobalFilter, Ordered {
private static final Logger log = LoggerFactory.getLogger(Filter1.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("filter1 running");
// fetch trace ID
String traceId = TraceContext.traceId();
log.info("filter1 traceId: {}", traceId);
// fetch segment ID
String segmentId = TraceContext.segmentId();
log.info("filter1 segmentId: {}", segmentId);
// fetch span ID
int spanId = TraceContext.spanId();
log.info("filter1 spanId: {}", spanId);
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -100;
}
}
@Component
public class GatewayFilter1 implements GatewayFilter {
private static final Logger log = LoggerFactory.getLogger(GatewayFilter1.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("gatewayFilter1 running");
return chain.filter(exchange);
}
}
|
Sorry, something went wrong.
|
Is there any filter not supposed? |
Sorry, something went wrong.
Any filter that implements the GlobalFilter and GatewayFilter interfaces can be supported. If the user only calls the code chain.filter(exchange) in each filter, the traceId will be fully recorded. However, if the user writes this code chain.filter(exchange).then(), the code in then() will not be able to obtain the traceId. In this case, you need to manually call WebFluxSkyWalkingTraceContext.traceId(exchange) in then() to obtain it. Here is an example: @Component
public class Filter1 implements GlobalFilter, Ordered {
private static final Logger log = LoggerFactory.getLogger(Filter1.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("filter1 running");
// fetch trace ID
String traceId = TraceContext.traceId();
log.info("filter1 traceId: {}", traceId);
// fetch segment ID
String segmentId = TraceContext.segmentId();
log.info("filter1 segmentId: {}", segmentId);
// fetch span ID
int spanId = TraceContext.spanId();
log.info("filter1 spanId: {}", spanId);
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
log.info("filter1 then running");
// fetch trace ID
String traceId2 = TraceContext.traceId();
log.info("filter1 then traceId: {}", traceId2);
// fetch segment ID
String segmentId2 = TraceContext.segmentId();
log.info("filter1 then segmentId: {}", segmentId2);
// fetch span ID
int spanId2 = TraceContext.spanId();
log.info("filter1 then spanId: {}", spanId2);
}));
}
@Override
public int getOrder() {
return -100;
}
}
@Component
public class Filter2 implements GlobalFilter, Ordered {
private static final Logger log = LoggerFactory.getLogger(Filter2.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("filter2 running");
// fetch trace ID
String traceId = TraceContext.traceId();
log.info("filter2 traceId: {}", traceId);
// fetch segment ID
String segmentId = TraceContext.segmentId();
log.info("filter2 segmentId: {}", segmentId);
// fetch span ID
int spanId = TraceContext.spanId();
log.info("filter2 spanId: {}", spanId);
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
String traceId2 = WebFluxSkyWalkingTraceContext.traceId(exchange);
log.info("filter2 then traceId: {}", traceId2);
String segmentId2 = WebFluxSkyWalkingTraceContext.segmentId(exchange);
log.info("filter2 then segmentId: {}", segmentId2);
int spanId2 = WebFluxSkyWalkingTraceContext.spanId(exchange);
log.info("filter2 then spanId: {}", spanId2);
}));
}
@Override
public int getOrder() {
return 10;
}
}
|
Sorry, something went wrong.
The GlobalFilter and GatewayFilter loaded by default by the Spring Gateway will also be intercepted. Do you think this is an unnecessary filter? |
Sorry, something went wrong.
|
I didn't have a concept which interceptor is necessary or unnecessary. Could you polish the codes by review? I think we are almost good. |
Sorry, something went wrong.
Thank you, I will adjust my code as follows public class GatewayFilterInterceptor implements InstanceMethodsAroundInterceptor {
private static final ThreadLocal<AtomicInteger> STACK_DEEP = ThreadLocal.withInitial(() -> new AtomicInteger(0));
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
if (isEntry()) {
ServerWebExchange exchange = (ServerWebExchange) allArguments[0];
EnhancedInstance enhancedInstance = getInstance(exchange);
AbstractSpan span = ContextManager.createLocalSpan("SpringCloudGateway/GatewayFilter");
if (enhancedInstance != null && enhancedInstance.getSkyWalkingDynamicField() != null) {
ContextManager.continued((ContextSnapshot) enhancedInstance.getSkyWalkingDynamicField());
}
span.setComponent(SPRING_CLOUD_GATEWAY);
}
}
public static EnhancedInstance getInstance(Object o) {
EnhancedInstance instance = null;
if (o instanceof DefaultServerWebExchange) {
instance = (EnhancedInstance) o;
} else if (o instanceof ServerWebExchangeDecorator) {
ServerWebExchange delegate = ((ServerWebExchangeDecorator) o).getDelegate();
return getInstance(delegate);
}
return instance;
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
if (isExit()) {
if (ContextManager.isActive()) {
ContextManager.stopSpan();
}
}
return ret;
}
@Override
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t) {
ContextManager.activeSpan().log(t);
}
private boolean isEntry() {
return STACK_DEEP.get().getAndIncrement() == 0;
}
private boolean isExit() {
boolean isExit = STACK_DEEP.get().decrementAndGet() == 0;
if (isExit) {
STACK_DEEP.remove();
}
return isExit;
}
}
|
Sorry, something went wrong.
|
I posted this discussion according to your comments, apache/skywalking#12860 |
Sorry, something went wrong.
Maybe you need to add spring-cloud-gateway plugin to your projcet. @huicunjun |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
…g-cloud-gateway-plugin #12839