Feign 打印请求日志

添加 feign 配置

import feign.Logger;
import org.springframework.context.annotation.Configuration;

/**
 * @author luozhanfeng
 * @version 1.0
 * @date 2022/7/4 17:01
 * @description
 */
@Configuration
public class FeignConfig {

    @Bean
    public Logger.Level feignLogLevel(){ 
        return Logger.Level.BASIC;
    }

    @Bean
    Logger feignLogger() {
        return new MyFeignLogger();
    }

}

  • NONE【性能最佳,适用于生产】:不记录任何日志(默认值)
  • BASIC【适用于生产环境追踪问题】:仅记录请求方法、URL、响应状态代码以及执行时间
  • HEADERS:记录BASIC级别的基础上,记录请求和响应的header。
  • FULL【比较适用于开发及测试环境定位问题】:记录请求和响应的header、body和元数 据。

 
自定义 feign 配置

import ch.qos.logback.core.util.FileUtil;
import com.alibaba.fastjson.JSON;
import feign.Logger;
import feign.Request;
import feign.Response;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.io.*;
import java.util.*;
import static feign.Util.decodeOrDefault;
import static java.nio.charset.StandardCharsets.UTF_8;

/**
 * @author luozhanfeng
 * @version 1.0
 * @date 2022/7/4 17:14
 * @description
 */

/**
 * Feign请求日志处理类
* 所有通过Feign请求的外部接口都会被监控 */
@Slf4j public class MyFeignLogger extends Logger { private static final ThreadLocal<Map<String, String>> logContext = new ThreadLocal<>(); private static final String PATH = "path"; private static final String METHOD = "method"; private static final String REQUEST_BODY = "body"; private static final String HEADER = "header"; private static final String TIME = "time"; /** * 构建headers字符串 */ private String builderHeaders(Map<String, Collection<String>> headersMap) { StringBuilder headers = new StringBuilder(); Iterator<Map.Entry<String, Collection<String>>> iterator = headersMap.entrySet().stream().iterator(); while (iterator.hasNext()) { Map.Entry<String, Collection<String>> next = iterator.next(); ArrayList<String> values = new ArrayList<>(next.getValue()); headers.append(next.getKey()) .append(":") .append(values.size() == 1 ? values.get(0) : JSON.toJSONString(values)) .append(iterator.hasNext() ? "|" : ""); } return headers.toString(); } /** * 请求拦截 */ @Override protected void logRequest(String configKey, Level logLevel, Request request) { Map<String, String> map = new HashMap<>(3); map.put(PATH, request.url()); map.put(TIME, System.currentTimeMillis() + ""); map.put(METHOD, request.httpMethod().name()); map.put(HEADER, builderHeaders(request.headers())); String body = request.body() == null ? null : request.charset() == null ? null : new String(request.body(), request.charset()); //文件上传不打印请求日志 if (StringUtils.contains(request.url(), "/helper/common/file/upload")) { body = null; } map.put(REQUEST_BODY, body); logContext.set(map); } /** * 响应拦截 */ @Override protected Response logAndRebufferResponse( String configKey, Level logLevel, Response response, long elapsedTime) throws IOException { Map<String, String> request = logContext.get(); logContext.remove(); // 返回参数 byte[] bodyData = streamToByteArray(response.body().asInputStream()); if (null != bodyData && bodyData.length > 0) { String responseBody = decodeOrDefault(bodyData, UTF_8, "Binary data"); log(request, response.status(), responseBody.replaceAll("\\s*|\t|\r|\n", "")); return response.toBuilder().body(bodyData).build(); } log(request, response.status(), null); return response; } /** * 异常拦截 */ @Override protected IOException logIOException(String configKey, Level logLevel, IOException ioe, long elapsedTime) { Map<String, String> request = logContext.get(); log.info("Feign-Error -> \npath -> {}\nmethod -> {}\nheaders -> {}\nrequest -> {}\n", request.get(PATH), request.get(METHOD), request.get(HEADER), request.get(REQUEST_BODY) ); logContext.remove(); return ioe; } /** * 日志打印 * * @param request * @param responseStatus * @param responseBody */ private void log(Map<String, String> request, Integer responseStatus, String responseBody) { log.info("\n" + "\npath -> {}" + "\ntime -> {}" + "\nmethod -> {}" + "\nstatus -> {}" + "\nheaders -> {}" + "\nrequest -> {}" + "\nresponse -> {}", request.get(PATH), (System.currentTimeMillis() - Long.parseLong(request.get(TIME))) + "ms", request.get(METHOD), responseStatus, request.get(HEADER), request.get(REQUEST_BODY), responseBody ); } @Override protected void log(String configKey, String format, Object... args) { if (log.isInfoEnabled()) { log.info(String.format(methodTag(configKey) + format, args)); } } /** * 输入流转byte[] * * @param inStream 文件流内容 * @return */ public static byte[] streamToByteArray(InputStream inStream) { if (inStream == null) { return null; } byte[] in2b = null; BufferedInputStream in = new BufferedInputStream(inStream); ByteArrayOutputStream swapStream = new ByteArrayOutputStream(); int rc = 0; try { while ((rc = in.read()) != -1) { swapStream.write(rc); } in2b = swapStream.toByteArray(); } catch (IOException e) { log.warn("streamToByteArray exception inStream:[{}]", inStream, e); } finally { closeIo(inStream, in, swapStream); } return in2b; } /** * 关闭流 */ public static void closeIo(Closeable... closeable) { if (null == closeable || closeable.length <= 0) { return; } for (Closeable cb : closeable) { try { if (null == cb) { continue; } cb.close(); } catch (IOException e) { throw new RuntimeException( FileUtil.class.getName(), e); } } } }

你可能感兴趣的:(JAVA,java)