Feign:自定义请求响应日志

本文作者:suxingrui
本文链接:https://blog.csdn.net/suxingrui/article/details/113739867
版权声明:本文为原创文章,转载请注明出处。

回顾2020年碰到的问题及解决方式
问题:自定义Feign输出的请求响应日志

问题发现:
调用外部接口时,一般都需要输出相关的请求和响应日志,以便于出现问题时的定位和分析。
使用Feign调用外部请求,默认输出的日志格式不符合个人的习惯,所以需要进行一定的扩展。
Feign:自定义请求响应日志_第1张图片

调查分析:
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、实现效果
在这里插入图片描述

你可能感兴趣的:(Java,Feign,Feign日志,FeignLogger)