本文作者:suxingrui
本文链接:https://blog.csdn.net/suxingrui/article/details/113739867
版权声明:本文为原创文章,转载请注明出处。
回顾2020年碰到的问题及解决方式
问题:自定义Feign输出的请求响应日志
问题发现:
调用外部接口时,一般都需要输出相关的请求和响应日志,以便于出现问题时的定位和分析。
使用Feign调用外部请求,默认输出的日志格式不符合个人的习惯,所以需要进行一定的扩展。
调查分析:
Feign默认的日志输出使用feign.slf4j.Slf4jLogger,参照可知,Feign预留了日志相关的扩展,
所以只需要实现feign.Logger的一个子类即可。
解决方法:
1、实现自定义继承feign.Logger的类FeignLogger,按自己需要输出日志
import feign.Request;
import feign.Response;
import feign.Util;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import static feign.Util.UTF_8;
import static feign.Util.decodeOrDefault;
import static feign.Util.valuesOrEmpty;
/**
* Feign Logger类
*
* @author suxingrui
* @time 2021/2/7 16:55
**/
public class FeignLogger extends feign.Logger {
private final org.slf4j.Logger log = LoggerFactory.getLogger("FeignLogger");
private String headers(Map<String, Collection<String>> headerMap) {
StringBuilder headers = new StringBuilder();
for (String field : headerMap.keySet()) {
for (String value : valuesOrEmpty(headerMap, field)) {
headers.append("\n").append(field).append(": ").append(value);
}
}
return headers.toString();
}
@Override
protected void logRequest(String configKey, Level logLevel, Request request) {
String url = request.url();
String body = "";
if (request.requestBody() != null) {
body = request.requestBody().asString();
}
log.info("Sending request {}\nbody: {}\nheader: {}", url, body, headers(request.headers()));
}
@Override
protected Response logAndRebufferResponse(String configKey, Level logLevel, Response response,
long elapsedTime) throws IOException {
int status = response.status();
String url = response.request().url();
String content = "";
if (response.body() != null && !(status == 204 || status == 205)) {
byte[] bodyData = Util.toByteArray(response.body().asInputStream());
if (bodyData.length > 0) {
content = decodeOrDefault(bodyData, UTF_8, "Binary data");
}
response = response.toBuilder().body(bodyData).build();
}
log.info("Received response code: {} {}ms for {} \nbody: {}", status, elapsedTime, url, content);
return response;
}
@Override
protected void log(String configKey, String format, Object... args) {
}
}
2、配置类
import feign.Logger;
import org.springframework.context.annotation.Bean;
/**
* Feign 配置
*
* @author suxingrui
* @time 2021/2/7 15:21
**/
public class FeignConfiguration {
@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
@Bean
public Logger feignLogger() {
return new FeignLogger();
}
}
3、配置,将配置类设置在FeignClient里
/**
* 测试Feign
*
* @author suxingrui
* @time 2021/2/7 14:11
**/
@FeignClient(name = "test-server", url = "${test.base.url}", path = "/test", primary = false, configuration = FeignConfiguration.class)
public interface TestFeignClient {
/**
* 用户列表
*/
@PostMapping("user/list")
ResultBean<List<User>> listUser(@RequestBody User req);
}
4、实现效果