springcloud 2.2.2 feign日誌打印
全局通用的配置方式
package cn.zhangfusheng.base.feign.config;
import feign.Logger;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @ClassName: FeignConfig
* @Author: ZFS
* @Date: 2019/4/11 17:49
*/
@Slf4j
@Configuration
@EnableFeignClients
public class FeignConfig {
/**
* feign 的日誌記錄
* @return
*/
@Bean
Logger.Level feignLoggerLevel() {
/* NONE, 不記錄日誌 (默認)。
BASIC, 只記錄請求方法和URL以及響應狀態代碼和執行時間。
HEADERS, 記錄請求和應答的頭的基本信息。
FULL, 記錄請求和響應的頭信息,正文和元數據。*/
log.debug("feign輸出full級別日誌:[ 記錄請求和響應的頭信息,正文和元數據]");
return Logger.Level.FULL;
}
}
package cn.zhangfusheng.base.feign.logger;
import feign.Logger;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.Arrays;
/**
* @author fusheng.zhang
* @Description
* @create 2020-04-16 13:31:00
*/
@Slf4j
@Component
public class FeignLogger extends Logger {
@Override
protected void log(String configKey, String format, Object... args) {
log.info("{}:{}", configKey, String.format(format, args));
}
}
優化日誌輸出格式
package cn.zhangfusheng.base.feign.logger;
import feign.Request;
import feign.Response;
import feign.Util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import static feign.Util.UTF_8;
import static feign.Util.decodeOrDefault;
/**
* @author fusheng.zhang
* @Description feign 日誌
* @create 2020-04-16 13:31:00
*/
@Slf4j
@Component
public class FeignLogger extends feign.Logger {
@Override
protected void log(String configKey, String format, Object... args) {
log.info("\n\t{}:{}", configKey, String.format(format, args));
}
@Override
protected void logRequest(String configKey, Level logLevel, Request request) {
StringBuilder logStr = new StringBuilder();
logStr.append(String.format("\n\t---> %s %s HTTP/1.1", request.httpMethod().name(), request.url()));
if (logLevel.ordinal() >= Level.HEADERS.ordinal()) {
request.headers().forEach((k, v) -> {
logStr.append(String.format("\n\t%s: %s", k, v));
});
int bodyLength = 0;
if (request.requestBody().asBytes() != null) {
bodyLength = request.requestBody().asBytes().length;
if (logLevel.ordinal() >= Level.FULL.ordinal()) {
String bodyText = request.requestBody() != null ? new String(request.requestBody().asBytes()) : null;
logStr.append(String.format("\n\trequestBody: %s", bodyText != null ? bodyText : "Binary data"));
}
}
logStr.append(String.format("\n\t---> END HTTP (%s-byte body)", bodyLength));
log(configKey, "%s", logStr);
}
}
@Override
protected Response logAndRebufferResponse(
String configKey, Level logLevel, Response response, long elapsedTime) throws IOException {
String reason = response.reason() != null && logLevel.compareTo(Level.NONE) > 0 ? " " + response.reason() : "";
int status = response.status();
StringBuilder logStr = new StringBuilder();
logStr.append(String.format("\n\t<--- HTTP/1.1 %s%s (%sms)", status, reason, elapsedTime));
if (logLevel.ordinal() >= Level.HEADERS.ordinal()) {
response.headers().forEach((k, v) -> {
logStr.append(String.format("\n\t%s: %s", k, v));
});
int bodyLength = 0;
if (response.body() != null && !(status == 204 || status == 205)) {
byte[] bodyData = Util.toByteArray(response.body().asInputStream());
bodyLength = bodyData.length;
if (logLevel.ordinal() >= Level.FULL.ordinal() && bodyLength > 0) {
logStr.append(String.format("\n\trequestBody: %s", decodeOrDefault(bodyData, UTF_8, "Binary data")));
}
logStr.append(String.format("\n\t<--- END HTTP (%s-byte body)", bodyLength));
log(configKey, "%s)", logStr);
return response.toBuilder().body(bodyData).build();
} else {
logStr.append(String.format("\n\t<--- END HTTP (%s-byte body)", bodyLength));
log(configKey, "%s)", logStr);
}
}
return response;
}
@Override
protected IOException logIOException(
String configKey, Level logLevel, IOException ioe, long elapsedTime) {
StringBuilder logStr = new StringBuilder();
logStr.append(String.format("\n\t<--- ERROR %s: %s (%sms)",
ioe.getClass().getSimpleName(), ioe.getMessage(), elapsedTime));
if (logLevel.ordinal() >= Level.FULL.ordinal()) {
StringWriter sw = new StringWriter();
ioe.printStackTrace(new PrintWriter(sw));
logStr.append(String.format("\n\t%s", sw.toString()));
logStr.append("\n\t<--- END ERROR");
log(configKey, "%s", logStr);
}
return ioe;
}
}
網上目前大多的配置方式如下
/**
* feign 的日誌記錄
* @return
*/
@Bean
Logger.Level feignLoggerLevel() {
/* NONE, 不記錄日誌 (默認)。
BASIC, 只記錄請求方法和URL以及響應狀態代碼和執行時間。
HEADERS, 記錄請求和應答的頭的基本信息。
FULL, 記錄請求和響應的頭信息,正文和元數據。*/
log.debug("feign輸出full級別日誌:[ 記錄請求和響應的頭信息,正文和元數據]");
return Logger.Level.FULL;
}
# 在配置logging.level
logging.level.某個feignclient的package: debugger