midway
midway copied to clipboard
【RFC】关于请求流数据记录的方案
现有问题
- 1、虽然我们一般采用 nginx 去记录访问日志,但是还是有用户希望在每次请求打一条记录
- 2、如果有 1 的需求,就会写一个中间件来完成,需要考虑中间件的加入顺序
- 3、需要考虑错误的情况和影响
目标
- 1、一种能在请求流中异步执行逻辑的方案,用于日志记录,异步数据转发等场景
- 2、让用户不需要自定义中间件,不需要考虑执行的顺序
- 3、可能需要多个阶段,比如请求开始,请求完成,以及错误的情况,可能会和错误过滤器有关联
关联 issue
#2251
这个是准备集成到框架中吗?如果有类似要将日志进行上传到Mysql或者ES上去的话,使用者是不是很难操作呢
@ddzyan 不会,和中间件使用类似。
我想请教下,一个请求处理的流程中, nginx
记录了请求和响应的日志,框架记录了在处理中报错的堆栈和必要的业务日志,那怎么将这两者进行关联呢。
我现在是在框架中间件中增加了traceId关联一次请求的所有日志输出,报错就将响应的traceId在框架日志或者日志平台上进行检索来排查问题
主要看 trace 和日志,nginx 一般不看。
- 1、trace 用来观察中间哪个外部节点出现问题,快速定位是程序本身还是外部接口
- 2、再看日志,你的日志可以带上 traceId 输出的,方便关联,不过一般如果定位是程序自己的问题,那堆栈一般比较明显,也能快速发现和解决了
- 3、nginx 有 access log,我们一般程序里不会打 access log,节省磁盘,如果打了,我理解也就是为了看下 nginx 是否配置和转发有误,毕竟只进入了 nginx,未进入到 node 的情况(很少)
我在程序中打 access.log 的目的是输出请求参数和响应结果,这样如果客户端出现了问题,那我可以拿到当时的请求参数,用来快速复现,也可以拿到当时的响应结果,用来排查是否客户端不兼容问题。
按照你说的这个方案,不在程序中输出的话,处理起来好像比较麻烦
一般是把错误的记录下来,毕竟日志打多了也是耗费 cpu 和性能的(很多人会打 info)。至于请求参数记录,这个其实很难再根据当时的请求参数快速复现(最多只能复现到第一层,如果有后续的调用情况,很难把每一层下游的节点都记录下来进行回归)
可以考虑把 otel 中间件集成到框架中,暴露几个接口(tag,log,createChildSpan),实现 tracer,log 一体化接口。 我现在是用 jaeger 来实现链路追踪和日志(函数、数据库的输入输出参数,异常信息),麻烦是每个组件都要写一套。
这个不太一样,一般我们只会打对外调用的节点(http/redis/grpc) 等,otel 组件也是为了让业务接入特别重要的自定义节点而存在的,目前 otel 的实现是比较先进的标准实现,他们倾向于直接用他们的 api 包去接入,而不是由框架再去包一层,所以 otel 组件也只是做了一些简单的 get 逻辑,另一方面 otel 不适合埋入框架,万一黄了不好剥离。