不知道你有没有经历过被日志支配的恐惧?我就经历过,以前在服务器上要找到一个请求经过所有链路的日志,并串联起来发现真的好难,而且有了日志还没用,最好还有有参数,有响应可以串联起来整个业务逻辑,最大程度进行场景复原,那段找日志的时光真是不堪回首,令人难忘,好在后来我离开了再没去服务器上看过日志了。
针对这种场景,怎么解呢?针对每次请求如果我们生成一个 id, 每次打印日志的时候都把这个 id 打印出来,那么当我们搜索每次请求的时候,根据这个 id 进行搜索就行了,本文也是基于这个思路来实现这个功能的。
请求链路
client —> tomcat —> other API
为了简化我们的请求逻辑,这里假设 client 访问我们的 tomcat, 然后 tomcat 访问外部服务
记录请求参数以及响应
为了记录请求参数以及响应结果,我们需要借助 Filter 来解决这个问题
记录 Restful 请求以及响应
一般而言,我们的服务会调用其他服务,无论你是使用的 dubbo 还是 http,我们都能通过拦截器来记录请求和响应参数,我们以 rest 来进行举例
由于我们的 response 是 stream, 我们想要消费多次 (一次返回给调用者,一次用于记录), 所以我们必须对这个 response 进行封装
Log4j2 配置
至此,我们的日志记录已经初具雏形了,这个时候当我们访问后端请求时,就可以通过返回的 requestId 去服务器上查询这次请求的链路日志
后台日志如下
查询时我们可以使用这样的命令
1 | cat api.log | grep ${requestId} |
这样就足够了吗?不,还不够好。我们可以将我们的日志发送到 ElasticSearch, 然后通过 Kibana 进行搜索,这样就不用每次查看日志都还要登录服务器了
自定义 appender
由于需要将日志发送到 ES, 所以我们需要自定义 appender 来发送日志,一个简单的 appender 的如下
然后在 Log4j 中进行如下配置即可
这里我的 es 使用的是本地安装的 es, 所以在运行的时候需要先启动 es
在 Kibana 中查询
至此,我们的日志平台就搭建起来了,以后别人就别想那么容易的推锅给你了。
所以的代码我都上传到了我的 github: (https://github.com/generalthink/code)
以供大家参考