首页 > 其他分享 >自定义Feign日志打印

自定义Feign日志打印

时间:2023-09-19 17:12:38浏览次数:41  
标签:ordinal Feign String 自定义 Level logLevel configKey import 日志

说明

想要自定义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 com.alibaba.fastjson.JSON;
import 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 java.util.HashMap;
import java.util.Map;

@Slf4j
public class LogFeignConfig 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) {
        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", JSON.toJSONString(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;
    }

}

全局生效

在自定义的打印feign日志类上打上@Component

局部feign接口生效

@FeignClient(configuration = {LogFeignConfig2.class})

标签:ordinal,Feign,String,自定义,Level,logLevel,configKey,import,日志
From: https://www.cnblogs.com/shareToAll/p/17715164.html

相关文章

  • Docker 日志缓存过大清理方案(亲测)
    Docker日志缓存过大清理方案(亲测)docker磁盘不足异常现象记录排查并定位问题解决方案参考地址自研产品推荐下载地址:docker磁盘不足异常现象记录docker-composeINTERNALERROR:cannotcreatetemporarydirectory!排查并定位问题1#查看磁盘占用情况[root@iZ25bmxsqmeZ~]#df......
  • 02_实战项目Zlog日志框架
    Zlog日志注释控制日志打印//printf("appstart\n");printf("appstart\n");printf("appstart\n");//printf("appstart\n");printf("appstart\n");//printf("appstart\n");printf("appstart\n&quo......
  • 支持SpEL表达式的自定义日志注解@SysLog介绍
    目录序言预期思路过程结果序言之前封装过一个日志注解,打印方法执行信息,功能较为单一不够灵活,近来兴趣来了,想重构下,使其支持表达式语法,以应对灵活的日志打印需求。该注解是方法层面的日志打印,如需更细的粒度,还请手撸log.xxx()。预期通过自定义注解,灵活的语法表达式,拦......
  • 自定义全局反序列化器
    以处理LocalDateTime格式的全局反序列化器为例,全局序列化器类似1、全局反序列化器代码importcom.fasterxml.jackson.annotation.JsonFormat;importcom.fasterxml.jackson.core.JsonParser;importcom.fasterxml.jackson.core.JsonProcessingException;importcom.fasterxml......
  • 支持多级别日志消息
    1、项目介绍本项目主要实现一个日志系统,其主要支持以下功能:支持多级别日志消息将日志分为不同等级的日志,有调试级别的日志、提示级别的日志、警告级别的日志、错误级别的日志、致命级别的日志……不同级别的日志应对着不同的场景。可以通过日志级别来实现限制输出的级别:当调试......
  • 自定义异常类处理
    在编程过程中,异常是不避免的,为了是我们的代码更加可靠,我们需要学会如何处理异常。一下是自定义异常以及异常处理的一个小案例:#一.自定义异常类MyException类,测试当用户输入的数字大于90,raise主动抛出并处理该异常classMyException(Exception):def__init__(self,msg):......
  • MySQL三大日志(binlog、redo log和undo log)详解
    硬核干货!一文掌握binlog、redolog、undolog(qq.com)MySQL日志:undolog、redolog、binlog(qq.com)MySQL三大日志(binlog、redolog和undolog)详解|JavaGuide(Java面试+学习指南)MySQL日志主要包括错误日志、查询日志、慢查询日志、事务日志、二进制日志几大类。其......
  • Vue学习七:自定义创建项目和vuex
    一、自定义创建项目默认的项目有很多包不全,需要的时候还要导包搭架子,因此我们可以自定义创建项目。选择的项目按照自己需要的设置,可参考如下参数设置。(eslink是一种代码规范)二、vuex1、vuex概述vuex是一个vue的状态管理工具,状态就是数据。大白话:vuex是一个插件,可以帮我们......
  • 畅购商城学习日志9
    nestedexceptionisorg.apache.ibatis.exceptions.PersistenceException:\r\n###Errorqueryingdatabase.Cause:org.springframework.jdbc.CannotGetJdbcConnectionException:FailedtoobtainJDBCConnection;nestedexceptioniscom.mysql.cj.jdbc.exceptions......
  • netty发送socket短连接请求,自定义报文头
    packagecom.chinaums.japi.util;importio.netty.bootstrap.Bootstrap;importio.netty.buffer.ByteBuf;importio.netty.buffer.Unpooled;importio.netty.channel.*;importio.netty.channel.nio.NioEventLoopGroup;importio.netty.channel.socket.SocketChannel;......