改造 cronet 库使得 安卓 release SDK 可以捕获 cronet 库 QUIC 相关日志实践

1、背景介绍

在我们移动端文件上传场景中,尝试使用 QUIC 协议来优化上传效果,为了准确的分析上传失败的任务,需要建立上传任务与 QUIC 连接的关联性;

当前每个上传任务结束时,或失败或成功都会上报一条日志,我们打算在启用了 QUIC 的上传任务中,增加一个字段保存 QUIC 相关信息,比如连接 ID、连接建立的日志、连接关闭的日志等,QUIC 连接关闭时会带上详细的关闭原因,帮助分析 QUIC 失败时客户端的状态,实现效果如下图,两条 APM 日志:

改造 cronet 库使得 安卓 release SDK 可以捕获 cronet 库 QUIC 相关日志实践_第1张图片

在服务端我们使用 Caddy 转发业务流量,Caddy 并发处理所有请求,因此各个请求的日志混在在一起,如果不对同一请求的日志加上唯一性标志,服务端对日志就失去了作用,而不同 QUIC 请求可以使用连接 ID 来标识;

为了把各个 QUIC 连接对应的日志关联起来,我们修改了 Caddy 源码,将 INFO、DEBUG 级别的每条日志加上了连接 ID,这需要修改 lucas-clemente/quic-go/interface.go 中 Session 接口,增加返回连接 ID 的方法,这样边能在每条日志输出时加上连接 ID,效果见下图,修改的日志用中括号将连接 ID 框起:

改造 cronet 库使得 安卓 release SDK 可以捕获 cronet 库 QUIC 相关日志实践_第2张图片

2、方案分析

cronet 库本身有调试日志,但数量太多,而且 release 版本不会输出这些日志,cronet 库使用的 chromium 网络栈,因此 QUIC 的日志可以使用 base::logging 来输出,它支持回调、输出到文件等方式,写文件要控制的细节太多,比如什么时候上传、如果日志上报失败怎么处理等问题;最后我们采取的方案是回调。

比如安卓实现的时候,Java 层会通过 JNI 层注册回调函数,该回调函数会将 base::logging 捕获的日志上报 APM,注册时会通过 JNI 层的方法向 base::logging 注册 C++ 层的回调方法,该回调方法负责将捕获的日志通过 JNI 层传递到 Java 层的回调函数,C++ 层注册回调方法的接口为 logging::SetLogMessageHandler。

你可能感兴趣的:(cronet,cronet,日志,安卓,quic)