网关的异常与日志定制参考
1、全局异常处理
全局异常处理的过滤器,尽量放到最外层。这个风格跟同步的区别有点大。
@Component(index = -99)
public class CloudGatewayErrorFilter implements CloudGatewayFilter {
static final Logger log = LoggerFactory.getLogger(AppFilter.class);
@Override
public Completable doFilter(ExContext ctx, ExFilterChain chain) {
return chain.doFilter(ctx).doOnError(e -> {
//转换响应状态
if (e instanceof StatusException) {
StatusException se = (StatusException) e;
ctx.newResponse().status(se.getCode());
} else {
ctx.newResponse().status(500);
}
//记录异常
log.warn("resp - err:{}", err);
});
}
}
其实可以作为下面转发日志记录的一部分:)
2、全局转发日志记录参考(可以包函异常处理)
使用 CloudGatewayFilter 对网关的转发进行日志记录(如果有需要?):
@Component(index = -99)
public class CloudGatewayLogFilter implements CloudGatewayFilter {
static final Logger log = LoggerFactory.getLogger(AppFilter.class);
@Override
public Completable doFilter(ExContext ctx, ExFilterChain chain) {
//记录请求日志
reqLog(ctx);
return chain.doFilter(ctx).doOnComplete(() -> {
//正确响应,记录日志
respLog(ctx);
}).doOnError(err -> {
//响应出错
if (e instanceof StatusException) {
StatusException se = (StatusException) e;
ctx.newResponse().status(se.getCode());
} else {
ctx.newResponse().status(500);
}
log.warn("resp - err:{}", err);
});
}
//记录请求日志
private void reqLog(ExContext ctx) {
log.info("req - method:{}", ctx.rawMethod());
log.info("req - headers:{}", ctx.rawHeaders());
log.info("req - query:{}", ctx.rawQueryString());
ctx.rawBody().andThen(asyncResult -> {
if (asyncResult.succeeded()) {
String bodyStr = asyncResult.result().toString();
log.info("req - body:{}", bodyStr); //不需要记录表单参数了,全在 body 里
} else {
log.warn("req - body:err:{}", asyncResult.cause());
}
});
}
//记录响应日志
private void respLog(ExContext ctx) {
log.info("resp - headers:{}", ctx.newResponse().getHeaders());
ExBody exBody = ctx.newResponse().getBody();
if (exBody instanceof ExBodyOfStream) {
//这是原始的 body 转发
ExBodyOfStream streamBody = (ExBodyOfStream) exBody;
((HttpClientResponse) streamBody.getStream()).body().andThen(asyncResult -> {
if (asyncResult.succeeded()) {
String bodyStr = asyncResult.result().toString();
log.info("resp - body:{}", bodyStr); //不需要记录表单参数了,全在 body 里
} else {
log.warn("resp - body:err:{}", asyncResult.cause());
}
});
} else if (exBody instanceof ExBodyOfBuffer) {
//body 是可以被修改的(如果你未修改,这块可以去掉)
ExBodyOfBuffer bufferBody = (ExBodyOfBuffer) exBody;
String bodyStr = bufferBody.getBuffer().toString();
log.info("resp - body:{}", bodyStr);
}
}
}