【Feign扩展】OpenFeign日志打印Http请求参数和响应数据

news/2024/4/26 6:00:58/文章来源:https://blog.csdn.net/qq_42985872/article/details/130379171

SpringBoot使用log4j2

在Spring Boot中所有的starter 都是基于spring-boot-starter-logging的,默认使用Logback。使用Log4j2的话,你需要排除 spring-boot-starter-logging 的依赖,并添加 spring-boot-starter-log4j2的依赖。

配置依赖

        <!-- 自定义验证注解 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId></dependency>

OpenFeign日志配置

feign的配置类

public class BaseFeignConfig {@BeanLogger.Level feignLoggerLevel() {return Logger.Level.FULL;}
}

单个服务应用配置类

@FeignClient(value = "crm-base",configuration = BaseFeignConfig.class )
public interface BaseFeign {@GetMapping("/getAppInfo")ResponseEx<Object> getAppInfo(@RequestParam(name = "appId") Integer appId);
}

日志级别配置

logging.level.com.charles.feign.BaseFeign=debug

打印效果

23-04-18 15:01:04 DEBUG http-nio-8080-exec-1 crm-emergency traceId- userId- com.linjiu.feign.BaseFeign.log:72:[BaseFeign#getAppInfo] ---> GET http://crm-base/getAppInfo?appId=-1 HTTP/1.1 
2023-04-18 15:01:04 DEBUG http-nio-8080-exec-1 crm-emergency traceId- userId- com.linjiu.feign.BaseFeign.log:72:[BaseFeign#getAppInfo] ---> END HTTP (0-byte body) 
2023-04-18 15:02:37 DEBUG http-nio-8080-exec-3 crm-emergency traceId- userId- com.linjiu.feign.BaseFeign.log:72:[BaseFeign#getAppInfo] ---> END HTTP (0-byte body) 
2023-04-18 15:02:38 DEBUG http-nio-8080-exec-3 crm-emergency traceId- userId- com.linjiu.feign.BaseFeign.log:72:[BaseFeign#getAppInfo] <--- HTTP/1.1 200 (205ms) 
2023-04-18 15:02:38 DEBUG http-nio-8080-exec-3 crm-emergency traceId- userId- com.linjiu.feign.BaseFeign.log:72:[BaseFeign#getAppInfo] connection: keep-alive 
2023-04-18 15:02:38 DEBUG http-nio-8080-exec-3 crm-emergency traceId- userId- com.linjiu.feign.BaseFeign.log:72:[BaseFeign#getAppInfo] content-type: application/json 
2023-04-18 15:02:38 DEBUG http-nio-8080-exec-3 crm-emergency traceId- userId- com.linjiu.feign.BaseFeign.log:72:[BaseFeign#getAppInfo] date: Tue, 18 Apr 2023 07:02:38 GMT 
2023-04-18 15:02:38 DEBUG http-nio-8080-exec-3 crm-emergency traceId- userId- com.linjiu.feign.BaseFeign.log:72:[BaseFeign#getAppInfo] keep-alive: timeout=60 
2023-04-18 15:02:38 DEBUG http-nio-8080-exec-3 crm-emergency traceId- userId- com.linjiu.feign.BaseFeign.log:72:[BaseFeign#getAppInfo] transfer-encoding: chunked 
2023-04-18 15:02:38 DEBUG http-nio-8080-exec-3 crm-emergency traceId- userId- com.linjiu.feign.BaseFeign.log:72:[BaseFeign#getAppInfo]  
2023-04-18 15:02:38 DEBUG http-nio-8080-exec-3 crm-emergency traceId- userId- com.linjiu.feign.BaseFeign.log:72:[BaseFeign#getAppInfo] {"data":[{ ...

源码解析

SynchronousMethodHandler#executeAndDecode,发送请求。如果日志级别不是Logger.Level.NONE,打印日志。

  Object executeAndDecode(RequestTemplate template, Options options) throws Throwable {Request request = targetRequest(template);if (logLevel != Logger.Level.NONE) {logger.logRequest(metadata.configKey(), logLevel, request);}Response response;long start = System.nanoTime();try {response = client.execute(request, options);// ensure the request is set. TODO: remove in Feign 12response = response.toBuilder().request(request).requestTemplate(template).build();} catch (IOException e) {if (logLevel != Logger.Level.NONE) {logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime(start));}throw errorExecuting(request, e);}long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);if (decoder != null)return decoder.decode(response, metadata.returnType());CompletableFuture<Object> resultFuture = new CompletableFuture<>();asyncResponseHandler.handleResponse(resultFuture, metadata.configKey(), response,metadata.returnType(),elapsedTime);try {if (!resultFuture.isDone())throw new IllegalStateException("Response handling not done");return resultFuture.join();} catch (CompletionException e) {Throwable cause = e.getCause();if (cause != null)throw cause;throw e;}}

Slf4jLogger#logRequest,判断是否允许debug日志输出

    protected void logRequest(String configKey, Level logLevel, Request request) {if (this.logger.isDebugEnabled()) {super.logRequest(configKey, logLevel, request);}}

Logger#logRequest,打印具体的请求日志。

  protected void logRequest(String configKey, Level logLevel, Request request) {log(configKey, "---> %s %s HTTP/1.1", request.httpMethod().name(), request.url());if (logLevel.ordinal() >= Level.HEADERS.ordinal()) {for (String field : request.headers().keySet()) {for (String value : valuesOrEmpty(request.headers(), field)) {log(configKey, "%s: %s", field, value);}}int bodyLength = 0;if (request.body() != null) {bodyLength = request.length();if (logLevel.ordinal() >= Level.FULL.ordinal()) {String bodyText =request.charset() != null? new String(request.body(), request.charset()): null;log(configKey, ""); // CRLFlog(configKey, "%s", bodyText != null ? bodyText : "Binary data");}}log(configKey, "---> END HTTP (%s-byte body)", bodyLength);}}

AsyncResponseHandler#handleResponse,处理响应。打印日志用的是logger.logAndRebufferResponse

  void handleResponse(CompletableFuture<Object> resultFuture,String configKey,Response response,Type returnType,long elapsedTime) {// copied fairly liberally from SynchronousMethodHandlerboolean shouldClose = true;try {if (logLevel != Level.NONE) {response = logger.logAndRebufferResponse(configKey, logLevel, response,elapsedTime);}} catch (final Exception e) {resultFuture.completeExceptionally(e);}}

Logger实体类创建,FeignClientFactoryBean#feign创建Feign。

    protected Builder feign(FeignContext context) {FeignLoggerFactory loggerFactory = (FeignLoggerFactory)this.get(context, FeignLoggerFactory.class);Logger logger = loggerFactory.create(this.type);Builder builder = ((Builder)this.get(context, Builder.class)).logger(logger).encoder((Encoder)this.get(context, Encoder.class)).decoder((Decoder)this.get(context, Decoder.class)).contract((Contract)this.get(context, Contract.class));this.configureFeign(context, builder);return builder;}

DefaultFeignLoggerFactory#create,创建日志类。

    public Logger create(Class<?> type) {return (Logger)(this.logger != null ? this.logger : new Slf4jLogger(type));}

使用slf4j进行创建,类型是com.linjiu.feign.BaseFeign。这也解释了需要配置logging.level.com.charles.feign.BaseFeign=debug才能输出日志。有时间专门来一篇博客,看看slf4j日志的生效逻辑和Springboot日志生效的逻辑。

    public Slf4jLogger(Class<?> clazz) {this(LoggerFactory.getLogger(clazz));}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_103824.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【小程序】input输入双向数据绑定

小程序中&#xff0c;input标签中的数据为单向绑定&#xff1a; <inputtype"number"bindinput"inputRealmoney"value"{{ amount }}"placeholder"请输入金额" />如上代码&#xff0c;我们绑定了输入框的数据amount&#xff0c;并…

Floccus插件 + 坚果云 实现不同浏览器间书签同步

&#xfeff; 在工作与学习中&#xff0c;我们时常希望在不同浏览器之间实现书签的同步&#xff1b;而一些传统的浏览器书签同步方案&#xff0c;或多或少都面临着一些问题——比如&#xff0c;Chrome浏览器尽管可以实现比较好的跨设备同步&#xff0c;但由于网络的限制可能导致…

多臂老虎机问题

1.问题简介 多臂老虎机问题可以被看作简化版的强化学习问题&#xff0c;算是最简单的“和环境交互中的学习”的一种形式&#xff0c;不存在状态信息&#xff0c;只有动作和奖励。多臂老虎机中的探索与利用&#xff08;exploration vs. exploitation&#xff09;问题一直以来都…

Java BIO

1.Java BIO(Blocking IO:同步并阻塞式IO)编程 1.1.基本介绍 1>.Java BIO就是传统的java io编程,其相关的类和接口在"java.io"包下; 2>.BIO(Blocking I/O): 同步阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处…

centos配置nacos集群

nacos配置集群 1.官方文档地址 https://nacos.io/zh-cn/docs/cluster-mode-quick-start.html 2.环境准备 1.64 bit OS&#xff0c;支持 Linux/Unix/Mac/Windows。&#xff08;至少3台&#xff0c;或者通过修改端口在一台服务器 启动多个nacos进行测试&#xff09;。 2.64 bit …

Three.js+TypeScript+Webpack学习记录(三)

使用环境参考 Node.js v16.19.1 正文 独立功能文件 我们不可能一直在 index.ts 中写代码&#xff0c;分离文件&#xff1a; // init.ts import * as THREE from threeexport const initScene () > {const scene new THREE.Scene()scene.background new THREE.Color(wh…

ChatGPT能用来写小说吗-gpt可以续写小说吗

怎么用ChatGPT写网文 ChatGPT是一个语言生成模型&#xff0c;可以用于生成各种文本&#xff0c;包括网文。下面是一些写网文的建议。 确定你的主题和情节。在开始写作之前&#xff0c;你需要确保你有一个明确的主题和情节&#xff0c;这可以帮助你更好地组织你的故事&#xff0…

电脑硬盘分区合并怎么操作?分享2个方法!

案例&#xff1a;电脑硬盘怎么分区&#xff1f; 【我把我的电脑硬盘分成了多个区域&#xff0c;这样可以方便存储和管理数据。现在我需要调整分区&#xff0c;对分区进行合并&#xff0c;但我不知道该如何操作&#xff0c;有没有小伙伴知道&#xff1f;】 在使用电脑的过程中…

【python视图3】networkx图操作示例

一、说明 根据定义&#xff0c;图是节点&#xff08;顶点&#xff09;以及已识别的节点对&#xff08;称为边、链接等&#xff09;的集合。在 NetworkX 中&#xff0c;节点可以是任何可哈希对象&#xff0c;例如文本字符串、图像、XML 对象、另一个图形、自定义节点对象等。 如…

perf生成火焰图

文章目录 1&#xff0c;top发现webserver进程空转情况下CPU占用高达200%2&#xff0c;使用性能分析工具perf来进行分析2.1&#xff0c;抓取采集样本2.2&#xff0c;使用perf简单分析性能数据 3&#xff0c;火焰图3.1&#xff0c;生成火焰图3.2&#xff0c;将生成的.svg文件用浏…

Chapter 4 :Constraining I/O Delay(ug903)

4.1 About Constraining I/O Delay 要在设计中准确地建模外部时序上下文&#xff0c;必须为输入和输出端口提供时序信息。由于XilinxVivado集成设计环境&#xff08;IDE&#xff09;只能识别FPGA边界内的时序&#xff0c;因此必须使用以下命令来指定超出这些边界的延迟…

数据库系统工程师——第五章 网络基础知识

文章目录 &#x1f4c2; 第五章、网络基础知识 &#x1f4c1; 5.1 计算机网络概述 &#x1f4d6; 5.1.1 计算机网络的概念 &#x1f4d6; 5.1.2 计算机网络的分类 &#x1f4d6; 5.1.3 网络的拓扑结构 &#x1f4c1; 5.2 网络硬件基础 &#x1f4d6; 5.2.1 网络设备 &…

【k8s】ruoyi微服务迁移到k8s

书接上回【传统方式部署Ruoyi微服务】&#xff0c;此刻要迁移至k8s。 环境说明 31 master &#xff0c; 32 node1 &#xff0c; 33 node2迁移思路 交付思路: 其实和交付到Linux主机上是一样的&#xff0c;无外乎将这些微服务都做成了Docker镜像; 1、微服务数据层: MySQL、 R…

“井电双控”地下水远程计量设施-实现地下水资源合理利用

“井电双控”地下水远程计量设施&#xff08;MGTR-W4122C&#xff09;是针对取水计量控制系统开发智能终端产品。集预收费、流量监测、电量监测、余额提醒、欠费停机、无线传输、远程控制等多种功能于一体&#xff0c;并可根据项目需求选择实体IC卡和APP电子卡取水两种方式。其…

换肤实现及LayoutInflater原理

文章目录 背景实现换肤步骤解析插件 apk 的包信息获取插件 apk 的 Resources 对象替换资源 简单的插件化换肤实现和存在的问题换肤如何动态刷新&#xff1f;控件换肤刷新的性能考虑如何降低 xml 布局中 View 的替换成本LayoutInflater 原理LayoutInflater.Factory2 替换 View 小…

David Silver Reinforcement Learning -- Markov process

1 Introduction 这个章节介绍关键的理论概念。 马尔科夫过程的作用&#xff1a; 1&#xff09;马尔科夫过程描述强化学习环境的方法&#xff0c;环境是完全能观测的&#xff1b; 2&#xff09;几乎所有的RL问题可以转换成MDP的形式&#xff1b; 2 Markov Processes 2.1 Mark…

从源码全面解析LinkedBlockingQueue的来龙去脉

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小黄&#xff0c;独角兽企业的Java开发工程师&#xff0c;CSDN博客专家&#xff0c;阿里云专家博主&#x1f4d5;系列专栏&#xff1a;Java设计模式、数据结构和算法、Kafka从入门到成神、Kafka从成神到升仙…

mall-swarm微服务商城系统

mall-swarm是一套微服务商城系统&#xff0c;采用了 Spring Cloud 2021 & Alibaba、Spring Boot 2.7、Oauth2、MyBatis、Docker、Elasticsearch、Kubernetes等核心技术&#xff0c;同时提供了基于Vue的管理后台方便快速搭建系统。mall-swarm在电商业务的基础集成了注册中心…

【Excel统计分析插件】上海道宁为您提供统计分析、数据可视化和建模软件——Analyse-it

Analyse-it是Microsoft Excel中的 统计分析插件 它为Microsoft Excel带来了 易于使用的统计软件 Analyse-it在软件中 引入了一些新的创新统计分析 Analyse-it与 许多Excel加载项开发人员不同 使用完善的软件开发和QA实践 包括单元/集成/系统测试 敏捷开发、代码审查 …

HCIA-RS实验-ENSP搭建一个基础的IP网络

HCIA-RS是华为认证网络工程师&#xff08;Routing & Switching&#xff09;的缩写。通过考取HCIA-RS证书&#xff0c;可以证明自己有能力设计、实现和维护小型网络。而HCIA-RS实验则是考试的一部分&#xff0c;是考生必须要完成的实践环节。这将是第一篇文章&#xff0c;后…