一、背景介绍
spring cloud 微服务架构中,需要对依赖服务的请求留痕(URL,出参,入参、耗时等)
1.现状
调用FeignClient(Integration类中)时 手工记录log
缺点:重复工作、log格式不统一
优点:充分满足个性化需求、灵活度极高(再说上天了)
2.目标
实现简洁统一的全局外部服务调用日志输出
示例如下:
get: GET 200 http://wwww.feigntest.com/dict/items?systemId=11 86 RESPONSE BODY:{"code":"000000","success":true} post: POST 200 http://wwww.feigntest.com/limitBill 85 REQUEST BODY:{"custNo":"121212","startTime":null,"endTime":null} RESPONSE BODY:{"code":"001001010","success":false} 异常: POST UnknownHostException http://wwww.feigntest.com/errorUri 206 REQUEST BODY:{"custNo":"121212"}
3.实现基础
基于FeignClient已有的全局请求日志处理类feign.Logger
feign.Logger日志输出级别为debug
输出header信息较多,大多服务并不需要
网上有类似资料,讲解如何启用feign.Logger、如何修改debug为info级别
本文增加对输出内容的简化.
二、如何使用
step 1.重写feign.Logger
-> 修改feign.Logger日志输出级别为info,简化输出内容
package com.cdfinance.mall.config; import feign.Request; import feign.Response; import feign.Util; import lombok.extern.slf4j.Slf4j; import java.io.IOException; import java.util.HashMap; import java.util.Map; import static feign.Util.UTF_8; import static feign.Util.decodeOrDefault; /** * Feign请求日志处理类<br/> * 所有通过Feign请求的外部接口都会被监控 * * @version V1.0 * @author: maoliang * @date: 2020/3/27 */ public class FeignLogger extends feign.Logger { static ThreadLocal<Map<String, String>> logContext = new ThreadLocal(); static String PATH = "path"; static String METHOD = "method"; static String REQUEST_BODY = "body"; protected void logRequest(String configKey, Level logLevel, Request request) { Map<String, String> logMap = new HashMap<>(3); logMap.put(PATH, request.url()); logMap.put(METHOD, request.method()); logMap.put(REQUEST_BODY, request.body() == null ? null : request.charset() == null ? null : new String(request.body(), request.charset())); logContext.set(logMap); } protected Response logAndRebufferResponse( String configKey, Level logLevel, Response response, long elapsedTime) throws IOException { Map<String, String> requetParam = logContext.get(); StringBuilder stringBuilder = new StringBuilder(); stringBuilder .append(requetParam.get(METHOD)).append(" ") .append(response.status()).append(" ") .append(requetParam.get(PATH)).append(" ") .append(elapsedTime); if (requetParam.get(REQUEST_BODY) != null) { stringBuilder.append(" REQUEST BODY:").append(requetParam.get(REQUEST_BODY)); } logContext.remove(); // 返回参数 if (response.body() != null && !(response.status() == 204 || response.status() == 205)) { byte[] bodyData = Util.toByteArray(response.body().asInputStream()); if (bodyData.length > 0) { String responseBody = decodeOrDefault(bodyData, UTF_8, "Binary data"); stringBuilder .append(" RESPONSE BODY:") .append(responseBody.replaceAll("\\s*|\t|\r|\n", "")); } log.info(stringBuilder.toString()); return response.toBuilder().body(bodyData).build(); } log.info(stringBuilder.toString()); return response; } protected IOException logIOException(String configKey, Level logLevel, IOException ioe, long elapsedTime) { Map<String, String> requetParam = logContext.get(); StringBuilder stringBuilder = new StringBuilder(); stringBuilder .append(requetParam.get(METHOD)).append(" ") .append(ioe.getClass().getSimpleName()).append(" ") .append(requetParam.get(PATH)).append(" ") .append(elapsedTime); if (requetParam.get(REQUEST_BODY) != null) { stringBuilder.append(" REQUEST BODY:").append(requetParam.get(REQUEST_BODY)); } log.warn(stringBuilder.toString()); logContext.remove(); return ioe; } protected void log(String configKey, String format, Object... args) { if (log.isInfoEnabled()) { log.info(String.format(methodTag(configKey) + format, args)); } } }
step 2.注册FeignLogger
-> 注册FeignLogger, 设置 Logger.Level为FULL
import feign.Logger; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * 注册FeignClient请求日志配置 * * @version V1.0 * @author: mlxnle * @date: 2020/04/01 */ public class FeignLoggerConfig { Logger.Level loggerLevel() { return Logger.Level.FULL; } Logger feignLogger() { return new FeignLogger(); // 你的继承类 } }
step 3.开始你的请求
-> 没有第三步! 惊不惊喜
相关推荐
3. **使用Feign Client**:在需要调用远程服务的地方,直接注入Feign Client,像调用本地方法一样调用远程服务。 4. **处理异常**:为Feign异常进行捕获和处理,比如处理HTTP状态码非200的情况。 5. **优化和扩展*...
3. **配置Feign**:在Spring Boot的配置文件中,可以设置Feign的全局配置,如超时时间、连接池大小等。 4. **自定义配置**:利用Feign的 SPI(Service Provider Interface)机制,实现自定义的配置类,扩展Feign的...
这可以通过两种方式进行:全局配置或针对特定Feign客户端进行配置。 ##### 全局配置 ```yaml feign: client: config: default: connectTimeout: 5000 readTimeout: 5000 loggerLevel: basic ...
search_client 可以集成这些工具,提供详细的请求链路日志,便于系统监控和问题定位。 总的来说,Spring Cloud Client 在这个例子中是整个微服务架构中的一个重要组成部分,它通过与 Spring Cloud 的其他组件协作,...
Spring Cloud 是一个基于 Spring Boot 实现的云应用开发工具集,它为开发者提供了在分布式系统(如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态)...
Spring Cloud 是一个基于 Spring Boot 实现的云应用开发工具集,它为开发者提供了在分布式系统(如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态)...
提供基于Feign的RestService动态创建 提供基于easyjson的编码器,解码器 集成负载均衡功能 提供多种param Expander 筛选器: 访问日志过滤器 编码过滤器 rr过滤器 全局响应过滤器 休息: 提供统一的异常处理 提供...
Spring Cloud 是一个基于 Spring Boot 实现的云应用开发工具集,它为开发者提供了在分布式系统(如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态等...
- **API Gateway**:Zuul作为API网关,实现统一的权限验证、日志记录、动态路由等功能。 - **微服务间通信**:使用Feign进行服务间的HTTP请求,或者使用RabbitMQ、Kafka等消息中间件实现异步通信。 - **配置管理*...
Spring Cloud是一套基于Spring Boot实现的微服务云应用开发框架,它为开发者提供了在分布式系统(如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态...
例如,你可能会看到Eureka的配置文件(eureka-client.properties或eureka-server.properties),Zuul的路由配置,Hystrix的断路器配置,以及服务间的Feign调用实现等。 此外,这个项目可能还包括了数据库连接配置、...
Spring Cloud 是一个基于 Spring Boot 实现的云应用开发工具集,它为开发者提供了在分布式系统(如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态)...
Spring Cloud 是一套基于 Spring Boot 实现的微服务云应用开发框架,它为开发者提供了在分布式系统(如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群...
SpringCloud是一个全面的云应用开发工具集,它为开发者提供了在分布式系统(如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态)快速构建一些常见...
Spring Cloud是一个全面的微服务解决方案,它为开发者提供了快速构建分布式系统中的一些常见模式,如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态...
Spring Cloud作为一个强大的微服务框架,为开发者提供了构建分布式系统中的配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态等多种功能。本资料集合了...
SpringCloud则是基于SpringBoot构建大型分布式系统的工具集,它提供了一整套解决方案,包括服务发现、配置中心、负载均衡、断路器、熔断机制、智能路由、微代理、控制总线、全局锁、领导选举、分布式会话、集群状态...
- Spring Boot Actuator 提供了许多生产就绪的功能,如健康检查、指标收集、审计日志等。 - 添加依赖: ```xml <groupId>org.springframework.boot <artifactId>spring-boot-starter-actuator ``` - 配置...
4. **服务消费者(first-client)**:这部分代码可能使用了Spring Cloud的Feign或者RestTemplate来消费服务提供者的接口,通过服务发现机制找到服务提供者的地址。 5. **断路器(Hystrix)**:断路器模式是应对服务...
而Spring Cloud则是一套为微服务提供配置管理、服务发现、断路器、智能路由、微代理、控制总线、全局锁、决策竞选、分布式会话和集群状态等工具的集合。 在集成GRPC和Spring Cloud的过程中,主要涉及以下几个关键...