自定义Feign日志打印

说明

想要自定义feign日志打印只需要继承feign.Logger抽象类,在自定义类中一般会重写三个方法

  • logRequest
    这个方法入参分别是String configKey, Logger.Level logLevel, Request request
    • configKey: feign调用的所在接口名+方法名
    • logLevel: 日志层级NONE,BASIC,HEADERS,FULL
    • request: 请求信息
  • logAndRebufferResponse
    这个方法入参分别是String configKey, Logger.Level logLevel, Response response, long elapsedTime。出参Response
    • configKey: feign调用的所在接口名+方法名
    • logLevel: 日志层级NONE,BASIC,HEADERS,FULL
    • response: 接口返回信息
    • elapsedTime: 调用接口耗时,单位ms
  • logIOException
    这个方法入参分别是String configKey, Logger.Level logLevel, IOException ioe, long elapsedTime。出参IOException
    • configKey: feign调用的所在接口名+方法名
    • logLevel: 日志层级NONE,BASIC,HEADERS,FULL
    • IOException: 接口调用返回异常信息
    • elapsedTime: 调用接口耗时,单位ms

自定义feign日志代码

import feign.Logger;
import feign.Request;
import feign.Response;
import feign.Util;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class FeignLogger extends Logger {

    @Override
    protected void log(String s, String s1, Object... objects) {
        log.info(String.format(methodTag(s) + s1, objects));
    }

    protected void logRequest(String configKey, Logger.Level logLevel, Request request) {
        // log.info("局部GlobalLogFeignLogger");
        this.log(configKey, "---> %s %s HTTP/1.1", request.httpMethod().name(), request.url());
        if (logLevel.ordinal() >= Logger.Level.BASIC.ordinal()) {
            String bodyText;
            if (logLevel.ordinal() >= Level.HEADERS.ordinal()) {
                Map<String, Object> headMap = new HashMap<>();
                for (String s : request.headers().keySet()) {
                    bodyText = s;
                    for (String value : Util.valuesOrEmpty(request.headers(), bodyText)) {
                        headMap.put(bodyText, value);
                    }
                }
                this.log(configKey, "---> 头信息 %s", headMap);
            }
            int bodyLength = 0;
            if (request.body() != null) {
                bodyLength = request.length();
                if (logLevel.ordinal() >= Logger.Level.BASIC.ordinal()) {
                    bodyText = request.charset() != null ? new String(request.body(), request.charset()) : null;
                    this.log(configKey, "入参---> %s", bodyText != null ? bodyText : "Binary data");
                }
            }
            if (logLevel.ordinal() >= Level.FULL.ordinal()) {
                this.log(configKey, "---> END HTTP (%s-byte body)", bodyLength);
            }
        }
    }

    protected Response logAndRebufferResponse(String configKey, Logger.Level logLevel, Response response, long elapsedTime) throws IOException {
        int status = response.status();
        if (logLevel.ordinal() >= Logger.Level.BASIC.ordinal()) {
            if (logLevel.ordinal() >= Level.FULL.ordinal()) {
                for (String field : response.headers().keySet()) {
                    for (String value : Util.valuesOrEmpty(response.headers(), field)) {
                        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());
                bodyLength = bodyData.length;
                if (logLevel.ordinal() >= Level.BASIC.ordinal() && bodyLength > 0) {
                    this.log(configKey, "出参<--- %s", Util.decodeOrDefault(bodyData, Util.UTF_8, "Binary data"));
                }
                if (logLevel.ordinal() >= Level.FULL.ordinal()) {
                    this.log(configKey, "<--- END HTTP (%s-byte body)", bodyLength);
                }
                this.log(configKey, "<--- 接口耗时 -- %sms", elapsedTime);
                return response.toBuilder().body(bodyData).build();
            }
            if (logLevel.ordinal() >= Level.FULL.ordinal()) {
                this.log(configKey, "<--- END HTTP (%s-byte body)", bodyLength);
            }
        }
        this.log(configKey, "<--- 接口耗时--%sms", elapsedTime);
        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);
        log.error("<---", ioe);
        if (logLevel.ordinal() >= Level.BASIC.ordinal()) {
            StringWriter sw = new StringWriter();
            ioe.printStackTrace(new PrintWriter(sw));
            this.log(configKey, "%s", sw.toString());
        }
        return ioe;
    }

}

局部生效

说明:只针对一个feignClient 接口生效,使用@FeignClient中的configuration指定即可

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.test.boot.param.FeignResultDto;
import com.test.boot.param.PageQueryDto;
import com.test.boot.param.TransferImportListInDto;
import com.test.boot.param.TransferImportListOutDto;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

@FeignClient(name = "stockFeign", url = "http://stock-center.net", configuration = {FeignLogger.class})
public interface StockFeign {

    @PostMapping("/api/v1/transferorder/queryBatchImportTransferOrder")
    FeignResultDto<Page<TransferImportListOutDto>> queryBatchTransferOrder(@RequestBody PageQueryDto<TransferImportListInDto> pageQueryDto);

}

全局生效

说明:@FeignClient中的configuration无需指定,加个配置类即可

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

@Configuration
public class CustomDecoderConfiguration {

    @Bean
    public Logger feignLogger() {
        return new FeignLogger();
    }
}

当局部和全局类同时存在的时候,局部的生效

posted @ 2023-09-19 17:01  品书读茶  阅读(667)  评论(0编辑  收藏  举报