1、首先需要设置属性logging.level.包名:debug。为什么要打开这个属性呢?
因为feign的logger实现类Slf4jLogger在调用log方法时,会判断是否开启了debug。
protectedvoidlog(StringconfigKey, Stringformat, Object... args) { // Not using SLF4J's support for parameterized messages (even though it would be more efficient)// because it would// require the incoming message formats to be SLF4J-specific.if (logger.isDebugEnabled()) { logger.debug(String.format(methodTag(configKey) +format, args)); } }
2、feign的日志级别
feign的日志级别包含下面几个
- NONE:不输出日志
- BASIC:输出请求方法及url,响应的状态码及响应时间
- HEADERS:输出请求和响应的头信息
- FULL:输出请求和响应的请求头,消息体及元数据
在发送请求时,会判断feign的日志级别,如果级别大于等于HEADERS,则输出请求头,如果级别大于等于FULL,则输出消息体。
protectedvoidlogRequest(StringconfigKey, LevellogLevel, Requestrequest) { log(configKey, "---> %s %s HTTP/1.1", request.httpMethod().name(), request.url()); if (logLevel.ordinal() >=Level.HEADERS.ordinal()) { for (Stringfield : request.headers().keySet()) { for (Stringvalue : valuesOrEmpty(request.headers(), field)) { log(configKey, "%s: %s", field, value); } } intbodyLength=0; if (request.body() !=null) { bodyLength=request.length(); if (logLevel.ordinal() >=Level.FULL.ordinal()) { StringbodyText=request.charset() !=null?newString(request.body(), request.charset()) : null; log(configKey, ""); // CRLFlog(configKey, "%s", bodyText!=null?bodyText : "Binary data"); } } log(configKey, "---> END HTTP (%s-byte body)", bodyLength); } }
在feign处理响应时,AsyncResponseHandler处理响应时判断日志级别输出日志,请求头或者消息体。
protectedResponselogAndRebufferResponse(StringconfigKey, LevellogLevel, Responseresponse, longelapsedTime) throwsIOException { Stringreason=response.reason() !=null&&logLevel.compareTo(Level.NONE) >0?" "+response.reason() : ""; intstatus=response.status(); log(configKey, "<--- HTTP/1.1 %s%s (%sms)", status, reason, elapsedTime); if (logLevel.ordinal() >=Level.HEADERS.ordinal()) { for (Stringfield : response.headers().keySet()) { for (Stringvalue : valuesOrEmpty(response.headers(), field)) { log(configKey, "%s: %s", field, value); } } intbodyLength=0; if (response.body() !=null&&!(status==204||status==205)) { // HTTP 204 No Content "...response MUST NOT include a message-body"// HTTP 205 Reset Content "...response MUST NOT include an entity"if (logLevel.ordinal() >=Level.FULL.ordinal()) { log(configKey, ""); // CRLF } byte[] bodyData=Util.toByteArray(response.body().asInputStream()); bodyLength=bodyData.length; if (logLevel.ordinal() >=Level.FULL.ordinal() &&bodyLength>0) { log(configKey, "%s", decodeOrDefault(bodyData, UTF_8, "Binary data")); } log(configKey, "<--- END HTTP (%s-byte body)", bodyLength); returnresponse.toBuilder().body(bodyData).build(); } else { log(configKey, "<--- END HTTP (%s-byte body)", bodyLength); } } returnresponse; }
3、如何设置日志级别的方式
3.1 通过属性配置
即feign.client.{contextId}.loggerLeve=BASIC、HEADERS或者FULL
可以发现在配置feign时,先是使用Configuration来配置,然后使用属性中的默认配置,最后使用属性中contextId对应的配置
protectedvoidconfigureFeign(FeignContextcontext, Feign.Builderbuilder) { FeignClientPropertiesproperties=applicationContext .getBean(FeignClientProperties.class); FeignClientConfigurerfeignClientConfigurer=getOptional(context, FeignClientConfigurer.class); setInheritParentContext(feignClientConfigurer.inheritParentConfiguration()); if (properties!=null&&inheritParentContext) { if (properties.isDefaultToProperties()) { configureUsingConfiguration(context, builder); configureUsingProperties( properties.getConfig().get(properties.getDefaultConfig()), builder); configureUsingProperties(properties.getConfig().get(contextId), builder); } else { configureUsingProperties( properties.getConfig().get(properties.getDefaultConfig()), builder); configureUsingProperties(properties.getConfig().get(contextId), builder); configureUsingConfiguration(context, builder); } } else { configureUsingConfiguration(context, builder); } }
3.2 @Configuration配置
publicclassFeignClientConfig { Logger.LevelfeignLoggerLevel() { returnLogger.Level.FULL; } }
此时是通过父子BeanFactory中查找Logger.Level,因为在子BeanFactory中没有,实际上是在父BeanFactory查找得到Logger.Level。
3.3 @FeignClient注解中的configuration来指定配置类。
此时是通过在子BeanFactory中查找得到Logger.Level。
配置的优先级为从高到低
配置文件中的contextId对应的属性->配置文件中的default对应的属性->FeignClient注解通过configuration指定的配置类->全局配置