fegin的日志配置
调试的时候,往往会发现,我调用fegin的方法,但是却总是调用的熔断器的方法,而日志却没有打印出来,导致无从下手。
现在就希望可以打印出fegin的请求参数和请求响应。
默认情况下feign是没有日志打印出来的,需要增加相关配置
一、创建Feign的配置文件,并在其中设置日志等级
package com.xy.ito.signatureservice.config;
import feign.Logger;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FeignLoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @NAME FeginConfig
* @DATE 2020-09-11 9:21
* @AUTHOR wzy
* @DESC TODO
**/
@Configuration
@Slf4j
public class FeignConfig implements RequestInterceptor {
//注意,因为fegin调用的时候,因为如果全部请求头复制赋值,会导致后续请求都沿用这个请求头,但是
//如果这个最初的请求头的配置有问题,比如content-length不一致,就会调用失败,所以只复制认证信息
@Override
public void apply(RequestTemplate template) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String values = request.getHeader(name);
// 跳过 content-length
if (name.equals("authorization")){
template.header(name, values);
}
}
} else {
log.info("feign interceptor error header:{}", template);
}
}
@Bean
Logger.Level feignLoggerLevel() {
//这里记录所有,根据实际情况选择合适的日志level
return Logger.Level.FULL;
}
@Bean
FeignLoggerFactory infoFeignLoggerFactory() {
return new InfoFeignLoggerFactory();
}
public static class InfoFeignLoggerFactory implements FeignLoggerFactory {
@Override
public Logger create(Class<?> type) {
return new InfoFeignLogger(LoggerFactory.getLogger(type));
}
}
private Map<String, String> getHeaders(){
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
Map<String, String> map = new LinkedHashMap<>();
if(request!=null){
Enumeration<String> enumeration = request.getHeaderNames();
while (enumeration.hasMoreElements()) {
String key = enumeration.nextElement();
String value = request.getHeader(key);
map.put(key, value);
}
}
return map;
}
}
这里设置了fegin的日志等级,我还实现了自己的日志打印方式
NONE,
BASIC,
HEADERS,
FULL;
简单明了
二、在客户端接口指定此配置
@FeignClient(name = "activity-server", fallback = ActivityServerClientFallback.class,configuration={FeignConfig.class})
@Component
public interface ActivityServerClient {
@PostMapping(value = "/act/task/f/complete",consumes = "application/json")
public Result completeTask(@RequestBody CompleteTaskDto completeTaskDto);
@GetMapping("/act/task/f/getTaskDetailDtoInfo")
public TaskDetailDto getTaskDetailDtoInfo(@RequestParam String taskId);
}
三、application.properties设置(可能不需要)
logging:
level:
com.xy.ito.signatureservice.mapper: debug
com.xy.ito.signatureservice.client: debug
四、进阶
可以做一些个性化处理
实现feign.logger
package com.xy.ito.signatureservice.config;
import feign.Logger;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FeignLoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @NAME FeginConfig
* @DATE 2020-09-11 9:21
* @AUTHOR wzy
* @DESC TODO
**/
@Configuration
@Slf4j
public class FeignConfig implements RequestInterceptor {
//注意,因为fegin调用的时候,因为如果全部请求头复制赋值,会导致后续请求都沿用这个请求头,但是
//如果这个最初的请求头的配置有问题,比如content-length不一致,就会调用失败,所以只复制认证信息
@Override
public void apply(RequestTemplate template) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String values = request.getHeader(name);
// 跳过 content-length
if (name.equals("authorization")){
template.header(name, values);
}
}
} else {
log.info("feign interceptor error header:{}", template);
}
}
@Bean
Logger.Level feignLoggerLevel() {
//这里记录所有,根据实际情况选择合适的日志level
return Logger.Level.FULL;
}
@Bean
FeignLoggerFactory infoFeignLoggerFactory() {
return new InfoFeignLoggerFactory();
}
public static class InfoFeignLoggerFactory implements FeignLoggerFactory {
@Override
public Logger create(Class<?> type) {
return new InfoFeignLogger(LoggerFactory.getLogger(type));
}
}
private Map<String, String> getHeaders(){
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
Map<String, String> map = new LinkedHashMap<>();
if(request!=null){
Enumeration<String> enumeration = request.getHeaderNames();
while (enumeration.hasMoreElements()) {
String key = enumeration.nextElement();
String value = request.getHeader(key);
map.put(key, value);
}
}
return map;
}
}
定义feign config
@Bean
Logger.Level feignLevel() {
return Logger.Level.FULL;
}
@Bean
FeignLoggerFactory infoFeignLoggerFactory() {
return new InfoFeignLoggerFactory();
}
public static class InfoFeignLoggerFactory implements FeignLoggerFactory {
@Override
public Logger create(Class<?> type) {
return new InfoFeignLogger(LoggerFactory.getLogger(type));
}
}
就是把日志工厂替换掉而已
https://my.oschina.net/u/3779841/blog/4282542
https://blog.csdn.net/sun_shaoping/article/details/82078873