ITPub博客

首页 > 数据库 > 数据库开发技术 > OpenFeign请求日志如何上报到Kafka?

OpenFeign请求日志如何上报到Kafka?

原创 数据库开发技术 作者:服务端技术栈 时间:2023-07-01 14:56:14 0 删除 编辑

前言

前面已经分析了OpenFeign三个组件了

Feign框架最核心可扩展组件通信Client详解

OpenFeign是怎样集成Ribbon负载均衡能力的?

OpenFeign集成Ribbon负载均衡-过滤和选择服务核心实现

OpenFeign重试组件Retryer原理

OpenFeign的RequestInterceptor组件你用过哪些场景?

今天还是继续分析OpenFeign的组件,分布式rpc服务调用的日志信息是非常关键的,OpenFeign提供了Logger组件,通过Logger组件可以实现openfeign接口调用的日志的打印或者上报到自定义日志服务器。

OpenFeign日志打印源码

OpenFeign如何打印日志的,我们可以看到OpenFeign执行请求主流程源码 位于feign.SynchronousMethodHandler#executeAndDecode

Object executeAndDecode(RequestTemplate template) 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);
} 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);boolean shouldClose = true;
try {//日志打印响应if (logLevel != Logger.Level.NONE) {response = logger.logAndRebufferResponse(metadata.configKey(), logLevel, response, elapsedTime);}
//相应解码Object result = decode(response);return result;
} catch (IOException e) {//打印响应解码日志if (logLevel != Logger.Level.NONE) {logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime);} throw errorReading(request, response, e);}}

从发起通信源码可以看出,OpenFeign分别在发起请求前使用Logger对象打印请求信息,发起请求后打印请求响应信息,响应解码的信息打印。

Logger抽象类定义好了打印日志的方法,同时OpenFeign给Logger抽象类提供了4个实现类。

由此可知,OpenFeign默认支持Slf4j,JavaLogger等日志组件。

OpenFeign默认使用Slf4j日志组件

我们在自动装配类FeignClientsConfiguration中,发现没有配置Logger的Bean实现。只是配置了FeignLoggerFactory的Bean是DefaultFeignLoggerFactory。

@Configuration(    proxyBeanMethods = false)public class FeignClientsConfiguration {
@Autowired(required = false) private Logger logger; @Bean @ConditionalOnMissingBean(FeignLoggerFactory.class) public FeignLoggerFactory feignLoggerFactory() { return new DefaultFeignLoggerFactory(this.logger);    }}

那么OpenFeign默认使用什么日志组件呢?通过feignLoggerFactory就可以看得出来。

public class DefaultFeignLoggerFactory implements FeignLoggerFactory {
private Logger logger;
public DefaultFeignLoggerFactory(Logger logger) { this.logger = logger; }
@Override public Logger create(Class<?> type) { //logger为空,默认使用log4j return this.logger != null ? this.logger : new Slf4jLogger(type); }
}

由此可知OpenFeign默认使用Slf4j日志组件打印日志。

日志级别

在Logger抽象类的方法参数里,对request和response方法日志打印还支持日志Level,日志等级共有4个。

public static enum Level {    NONE,//不打印    BASIC, //打印基本信息    HEADERS,//只打印请求头和响应    FULL; //全部打印
private Level() { }}

定制日志组件与日志级别

  • 针对单个Feign客户端

public class TestFeignClientConfiguration {        @Bean    public Logger logger() {        return new Logger.JavaLogger();    }        @Bean     public Logger.Level level() {        return  Logger.Level.FULL;    }}

@RestController@FeignClient(value = "fox-server", configuration = TestFeignClientConfiguration.class)public interface FeignService { @PostMapping("/get") String getName(@RequestBody @Validated DemoRequest request);}


  • 针对全局Feign客户端

public class TestFeignClientConfiguration {        @Bean    public Logger logger() {        return new Logger.JavaLogger();    }        @Bean     public Logger.Level level() {        return  Logger.Level.FULL;    }}


  • 自定义日志组件

 

上方我们是使用OpenFeign默认的日志实现,我们也可以自己实现自己的日志组件,只要继承抽象类feign.Logger,实现log方法。

真实的生产环境,由于我们是容器部署,我们的日志一般会上报到云平台,比如我们想把日志上报到kafka,提供给监控平台或者日志云平台分析等。

public class CustomLogger extends Logger {
@Resource Producer producer; @Override protected void log(String s, String s1, Object... objects) { //上报到kafka producer.send(new Message(s), "topic"); }}

二、总结

OpenFeign日志组件实现还是比较简单的,他和其他OpenFeign组件一样提供了的扩展点,我们可以按需实现自己的日志组件,实现个性化的日志打印或者日志上报功能,你在生产环境有没有使用过OpenFeign日志组件呢?欢迎评论区留言分享讨论。

原文作者:服务端技术栈;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2019-03-08

  • 博文量
    97
  • 访问量
    41433