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

前言
前面已经分析了OpenFeign三个组件了
OpenFeign集成Ribbon负载均衡-过滤和选择服务核心实现
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。
proxyBeanMethods = false)public class FeignClientsConfiguration {private Logger logger;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;}public Logger create(Class<?> type) {//logger为空,默认使用log4jreturn 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 {public Logger logger() {return new Logger.JavaLogger();}public Logger.Level level() {return Logger.Level.FULL;}}public interface FeignService {String getName( DemoRequest request);}
针对全局Feign客户端
public class TestFeignClientConfiguration {public Logger logger() {return new Logger.JavaLogger();}public Logger.Level level() {return Logger.Level.FULL;}}
自定义日志组件
上方我们是使用OpenFeign默认的日志实现,我们也可以自己实现自己的日志组件,只要继承抽象类feign.Logger,实现log方法。
真实的生产环境,由于我们是容器部署,我们的日志一般会上报到云平台,比如我们想把日志上报到kafka,提供给监控平台或者日志云平台分析等。
public class CustomLogger extends Logger {Producer producer;protected void log(String s, String s1, Object... objects) {//上报到kafkaproducer.send(new Message(s), "topic");}}
二、总结
OpenFeign日志组件实现还是比较简单的,他和其他OpenFeign组件一样提供了的扩展点,我们可以按需实现自己的日志组件,实现个性化的日志打印或者日志上报功能,你在生产环境有没有使用过OpenFeign日志组件呢?欢迎评论区留言分享讨论。
原文作者:服务端技术栈;如有侵权,请联系管理员删除。