当在通量的doOnNext块中遇到日志语句时,traceid和spanId不会被填充。但在块外,它会在webFilter中打印出来。下面是使用Sleuth的Reactive SpringBoot应用程序中的WebFlitter实现。
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信息[emp mgmt,4edae7c9825b4698,4edae7c9825b4698,false]6596-[Cor-http-nio-3]c.a.e.p.config.APILoggingFilter:之前的服务请求URLhttp://localhost:8083/api/v1/addEmp
2023-06-22 22:43:40.867信息[emp mgmt,4edae7c9825b4698,4edae7c9825b4698,false]6596-[Cor-http-nio-3]c.a.e.p.config.APILoggingFilter:之后的服务请求URLhttp://localhost:8083/api/v1/addEmp
2023-06-22 22:43:40.935信息
[emp mgmt,,]
6596-[cor-http-nio-3]c.a.e.p.config.APILoggingFilter:Service Request json,http://localhost:8083/api/v1/getEmp{
“uId”:null,
“empId”:“932046783773”,
“empName”:“Adam”,
“idNumber”:“860937”
}
2023-06-22 22:43:49.270信息[emp mgmt,4edae7c9825b4698,4edae7c9825b4678,false]6596-[并行-2]配置.APILoggingFilter:服务响应,URLhttp://localhost:8083/api/v1/addEmp
2023-06-22 22:43:49.283信息[emp mgmt,4edae7c9825b4698,4edae7c9825b4698,false]6596-[并行-2]配置.APILoggingFilter:服务响应,URLhttp://localhost:8083/api/v1/addEmp{
“uId”:76543467,
“empId”:“932046783773”,
“empName”:“Adam”,
“idNumber”:“860937”
}
带有“Service Request json”的日志语句没有traceId和SpanId。
使用弹簧webFlux:5.1.5.RELEASE和Sleuth 2.1.0.RELEASE。
请帮忙。