期望:
输出自己想要的日志格式,包含请求参数,响应参数,响应时间,请求URL
处理方法:
1、打开日志
2、继承: feign.Logger
实现:logAndRebufferResponse
/**
*打开日志
*/
@Configuration
public class FeignLogConfiguration {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.BASIC;
}
}
/**
*继承: feign.Logger
*实现:logAndRebufferResponse
**/
@Component
public class RemoteLogger extends Logger {
private static final PosLogger logger = new PosLogger(RemoteLogger.class);
@Override
protected void log(String s, String s1, Object... objects) {
}
@Override
protected void logRequest(String configKey, Logger.Level logLevel, Request request) {
}
@Override
protected Response logAndRebufferResponse(String configKey, Logger.Level logLevel, Response response, long elapsedTime) throws IOException {
if (response.body() != null) {
String result="";
byte[] bodyData = Util.toByteArray(response.body().asInputStream());
int bodyLength = bodyData.length;
if (bodyLength > 0) {
result = Util.decodeOrDefault(bodyData, Util.UTF_8, "Binary data");
}
Response build = response.toBuilder().body(bodyData).build();
Request request = build.request();
String bodyText = request.charset() != null ? new String(request.body(), request.charset()) : null;
// 请求URL request.url()
// 请求参数 bodyText
// 请求结果 result
// 请求耗时 elapsedTime
//logger.info();
return build;
}
return response;
}
protected IOException logIOException(String configKey,
Level logLevel,
IOException ioe,
long elapsedTime) {
//IOException 自带log输出即可 logger.error();
// com.netflix.client.ClientException: Load balancer does not have available server for client: lzh-cloud-test 服务没发现未进IO异常
return ioe;
}
}
NONE,无记录(DEFAULT)。
BASIC,只记录请求方法和URL以及响应状态代码和执行时间。
HEADERS,记录基本信息以及请求和响应标头。
FULL,记录请求和响应的头文件,正文和元数据。
特定类指定特定日志级别:
logging:
level:
com.lzh.cloud.feign.UserFeignClient: DEBUG
Logger
//构造方法
Logger();
//请求configKey长度处理
methodTag(String configKey);
//输出log日志
log(String var1, String var2, Object... var3);
//输出请求相关信息
logRequest(String configKey, Logger.Level logLevel, Request request)
//输出重试信息
logRetry(String configKey, Logger.Level logLevel)
//输出响应信息
logAndRebufferResponse(String configKey, Logger.Level logLevel, Response response, long elapsedTime)
//输出IO异常信息
logIOException(String configKey, Logger.Level logLevel, IOException ioe, long elapsedTime)
//默认的几个类实现
NoOpLogger
JavaLogger
ErrorLogger
//日志不同级别
Level
源码:
public abstract class Logger {
public Logger() {
}
protected static String methodTag(String configKey) {
return '[' + configKey.substring(0, configKey.indexOf(40)) + "] ";
}
protected abstract void log(String var1, String var2, Object... var3);
protected void logRequest(String configKey, Logger.Level logLevel, Request request) {
this.log(configKey, "---> %s %s HTTP/1.1", request.method(), request.url());
if (logLevel.ordinal() >= Logger.Level.HEADERS.ordinal()) {
Iterator var4 = request.headers().keySet().iterator();
String bodyText;
while(var4.hasNext()) {
bodyText = (String)var4.next();
Iterator var6 = Util.valuesOrEmpty(request.headers(), bodyText).iterator();
while(var6.hasNext()) {
String value = (String)var6.next();
this.log(configKey, "%s: %s", bodyText, value);
}
}
int bodyLength = 0;
if (request.body() != null) {
bodyLength = request.body().length;
if (logLevel.ordinal() >= Logger.Level.FULL.ordinal()) {
bodyText = request.charset() != null ? new String(request.body(), request.charset()) : null;
this.log(configKey, "");
this.log(configKey, "%s", bodyText != null ? bodyText : "Binary data");
}
}
this.log(configKey, "---> END HTTP (%s-byte body)", bodyLength);
}
}
protected void logRetry(String configKey, Logger.Level logLevel) {
this.log(configKey, "---> RETRYING");
}
protected Response logAndRebufferResponse(String configKey, Logger.Level logLevel, Response response, long elapsedTime) throws IOException {
String reason = response.reason() != null && logLevel.compareTo(Logger.Level.NONE) > 0 ? " " + response.reason() : "";
int status = response.status();
this.log(configKey, "<--- HTTP/1.1 %s%s (%sms)", status, reason, elapsedTime);
if (logLevel.ordinal() >= Logger.Level.HEADERS.ordinal()) {
Iterator var8 = response.headers().keySet().iterator();
while(var8.hasNext()) {
String field = (String)var8.next();
Iterator var10 = Util.valuesOrEmpty(response.headers(), field).iterator();
while(var10.hasNext()) {
String value = (String)var10.next();
this.log(configKey, "%s: %s", field, value);
}
}
int bodyLength = 0;
if (response.body() != null && status != 204 && status != 205) {
if (logLevel.ordinal() >= Logger.Level.FULL.ordinal()) {
this.log(configKey, "");
}
byte[] bodyData = Util.toByteArray(response.body().asInputStream());
int bodyLength = bodyData.length;
if (logLevel.ordinal() >= Logger.Level.FULL.ordinal() && bodyLength > 0) {
this.log(configKey, "%s", Util.decodeOrDefault(bodyData, Util.UTF_8, "Binary data"));
}
this.log(configKey, "<--- END HTTP (%s-byte body)", bodyLength);
return response.toBuilder().body(bodyData).build();
}
this.log(configKey, "<--- END HTTP (%s-byte body)", Integer.valueOf(bodyLength));
}
return response;
}
protected IOException logIOException(String configKey, Logger.Level logLevel, IOException ioe, long elapsedTime) {
this.log(configKey, "<--- ERROR %s: %s (%sms)", ioe.getClass().getSimpleName(), ioe.getMessage(), elapsedTime);
if (logLevel.ordinal() >= Logger.Level.FULL.ordinal()) {
StringWriter sw = new StringWriter();
ioe.printStackTrace(new PrintWriter(sw));
this.log(configKey, sw.toString());
this.log(configKey, "<--- END ERROR");
}
return ioe;
}
public static class NoOpLogger extends Logger {
public NoOpLogger() {
}
protected void logRequest(String configKey, Logger.Level logLevel, Request request) {
}
protected Response logAndRebufferResponse(String configKey, Logger.Level logLevel, Response response, long elapsedTime) throws IOException {
return response;
}
protected void log(String configKey, String format, Object... args) {
}
}
public static class JavaLogger extends Logger {
final java.util.logging.Logger logger = java.util.logging.Logger.getLogger(Logger.class.getName());
public JavaLogger() {
}
protected void logRequest(String configKey, Logger.Level logLevel, Request request) {
if (this.logger.isLoggable(java.util.logging.Level.FINE)) {
super.logRequest(configKey, logLevel, request);
}
}
protected Response logAndRebufferResponse(String configKey, Logger.Level logLevel, Response response, long elapsedTime) throws IOException {
return this.logger.isLoggable(java.util.logging.Level.FINE) ? super.logAndRebufferResponse(configKey, logLevel, response, elapsedTime) : response;
}
protected void log(String configKey, String format, Object... args) {
if (this.logger.isLoggable(java.util.logging.Level.FINE)) {
this.logger.fine(String.format(methodTag(configKey) + format, args));
}
}
public Logger.JavaLogger appendToFile(String logfile) {
this.logger.setLevel(java.util.logging.Level.FINE);
try {
FileHandler handler = new FileHandler(logfile, true);
handler.setFormatter(new SimpleFormatter() {
public String format(LogRecord record) {
return String.format("%s%n", record.getMessage());
}
});
this.logger.addHandler(handler);
return this;
} catch (IOException var3) {
throw new IllegalStateException("Could not add file handler.", var3);
}
}
}
public static class ErrorLogger extends Logger {
public ErrorLogger() {
}
protected void log(String configKey, String format, Object... args) {
System.err.printf(methodTag(configKey) + format + "%n", args);
}
}
public static enum Level {
NONE,
BASIC,
HEADERS,
FULL;
private Level() {
}
}
}