使用 Sleuth 的 webflux 应用程序中的 Flux doOnNext lambda 块内未打印 TraceId / SpanId

问题描述 投票:0回答:1

当在通量的 doOnNext 块内遇到日志语句时,traceid 和 spanId 不会被填充。但在块之外,它会在 webFilter 中打印。下面是带有 Sleuth 的响应式 SpringBoot 应用程序中的 WebFliter 实现。

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.reactivestreams.Publisher;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.channels.Channels;

@Slf4j
@Configuration
public class APILoggingFilter implements WebFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        ServerHttpRequest httpRequest = exchange.getRequest();
        final String httpUrl = httpRequest.getURI().toString();

        ServerHttpRequestDecorator loggingServerHttpRequestDecorator = new ServerHttpRequestDecorator(exchange.getRequest()) {
            String requestBody = "";

            @Override
            public Flux<DataBuffer> getBody() {
                log.info("Service Request URL before {}", httpUrl);
                Flux<DataBuffer> response =  super.getBody().doOnNext(dataBuffer -> {
                    try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
                        Channels.newChannel(byteArrayOutputStream).write(dataBuffer.asByteBuffer().asReadOnlyBuffer());
                        requestBody = IOUtils.toString(byteArrayOutputStream.toByteArray(), "UTF-8").replaceAll(System.lineSeparator(),StringUtils.EMPTY);
                        log.info(" Service Request json, {}", httpUrl, requestBody);
                    } catch (IOException e) {
                        log.info("Service Request, URL {}, {}, {}", httpUrl, requestBody, e);
                    }
                });
                log.info("Service Request URL after {}", httpUrl);
                return response;
            }
        };

        ServerHttpResponseDecorator loggingServerHttpResponseDecorator = new ServerHttpResponseDecorator(exchange.getResponse()) {
            String responseBody = "";
            @Override
            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                Mono<DataBuffer> buffer = Mono.from(body);
                log.info("Service Response, URL {}", httpUrl);
                return super.writeWith(buffer.doOnNext(dataBuffer -> {
                    try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
                        Channels.newChannel(byteArrayOutputStream).write(dataBuffer.asByteBuffer().asReadOnlyBuffer());
                        responseBody = IOUtils.toString(byteArrayOutputStream.toByteArray(), "UTF-8").replaceAll(System.lineSeparator(), StringUtils.EMPTY);
                        log.info("Service Response, URL {}, {}", httpUrl, responseBody);
                    } catch (Exception e) {
                        log.info("Service Response, URL {}, {}, {}", httpUrl, responseBody, e);
                    }
                }));
            }
        };
        return chain.filter(exchange.mutate().request(loggingServerHttpRequestDecorator).response(loggingServerHttpResponseDecorator).build());
    }

}

打印日志:

2023-06-22 22:43:40.859 INFO [emp-mgmt,4edae7c9825b4698,4edae7c9825b4698,false] 6596 --- [ctor-http-nio-3] c.a.e.p.config.APILoggingFilter :http://localhost 之前的服务请求 URL :8083/api/v1/addEmp 2023-06-22 22:43:40.867 INFO [emp-mgmt,4edae7c9825b4698,4edae7c9825b4698,false] 6596 --- [ctor-http-nio-3] c.a.e.p.config.APILoggingFilter :http://localhost 之后的服务请求 URL: 8083/api/v1/addEmp 2023-06-22 22:43:40.935 INFO [emp-mgmt,,,] 6596 --- [ctor-http-nio-3] c.a.e.p.config.APILoggingFilter :服务请求 json,http://localhost:8083 /api/v1/getEmp, { “uId”:空, "empId": "932046783773", "empName": "亚当", "id 号": "860937" }

2023-06-22 22:43:49.270 INFO [emp-mgmt,4edae7c9825b4698,4edae7c9825b4698,false] 6596 --- [parallel-2] config.APILoggingFilter:服务响应,URL http://localhost:8083/api/ v1/addEmp 2023-06-22 22:43:49.283 INFO [emp-mgmt,4edae7c9825b4698,4edae7c9825b4698,false] 6596 --- [parallel-2] config.APILoggingFilter:服务响应,URL http://localhost:8083/api/v1 /addEmp, { “用户ID”:76543467, "empId": "932046783773", "empName": "亚当", "id 号": "860937" }

带有“Service Request json”的日志语句没有traceId和SpanId。

使用 spring-webFlux:5.1.5.RELEASE 和 Sleuth 2.1.0.RELEASE。 请帮忙。

java spring-boot spring-webflux reactive-programming spring-cloud
1个回答
0
投票

这个问题你解决了吗?现在面临同样的问题:(

© www.soinside.com 2019 - 2024. All rights reserved.