淘宝客户端诊断体系升级实践

淘系技术 2021-09-15 16:20


淘宝作为一个航母级的应用,每天都有数亿的用户在使用。保证客户端的稳定性是我们的首要目标。为此,我们也提出了5-15-60的目标。即问题告警时,5分钟响应,15分钟定位,60分钟恢复。


但是现有的排查体系并不能很好的达到这个目标,分析下来主要原因是:


监控阶段


  1. 通过Crash堆栈、异常信息进行聚合统计,不够精细准确,不够灵敏;

  2. 监控到异常后,端侧行为比较单一,只上报异常信息,无法提供更多有用数据;

  3. 手淘大部分问题都和线上变更有关,但是缺少对变更质量的监控。


排查阶段


  1. 监控上报的异常信息不足,依赖日志进行问题排查;

  2. Crash或异常时不会主动上传日志,需要手动捞取, 用户不在线获取不到日志;

  3. 获取日志之后:

    1. 缺少分类,缺乏标准,日志杂乱,看不懂其他模块的日志;

    2. 缺少场景信息,无法完整的重现异常时用户的操作场景;

    3. 缺少整个生命周期相关的事件信息,无法掌握app的运行情况;

    4. 各个模块上下游的日志信息无法有效关联形成完整链路;

    5. 现有日志可视化工具功能较弱,无法提高排查效率;

  4. 问题排查靠人工分析,效率低下,相同问题缺少沉淀;

  5. 各个系统间的数据缺少关联,需要到多个平台获取数据。


诊断体系升级思路


针对以上现有问题,我们重新设计了整个无线运维排查诊断体系的架构。在新的架构中,我们引入了场景的概念。以往端上发生的异常都是一个个独立的事件,没有办法针对不同的异常做更精细的处理和数据收集。而引入场景概念后,一个场景可能是一个异常和多种条件的组合,针对不同的场景可以做配置,使得异常信息的收集更加丰富,更加精准。


同时我们重新定义了端侧异常数据,主要包括标准的Log日志数据、记录调用链路的Trace全链路数据、运行时相关的Metric指标数据以及发生异常时的现场快照数据。平台侧可以利用异常数据进行监控和告警。也可以对这些数据进行可视化的解析,针对业务的差异,平台提供了插件化的能力来解析数据。利用这些语义化后的信息,平台可以进行初步的问题诊断。


所以接下来要实现的目标是:


  1. 实现端侧场景化的监控运维;

  2. 升级日志体系,实现LOG、TRACE、METRIC数据整合, 提供更加丰富和精准的排查信息;

  3. 完成高可用体系数据整合,提供面向问题排查的标准化接⼝和平台;

  4. 插件化支撑平台赋能,业务自定义诊断插件,完成诊断体系平台间对接;

  5. 平台依据诊断信息,给出诊断结果,能做到自动化、智能化;

  6. 依据诊断结果给出解决方案或提出整改需求,形成从需求->研发->发布->监控->排查->诊断->修复->需求的闭环。


日志体系升级


目前分析运行日志还是端侧排查问题的主要手段,前面也提到我们的日志本身存在一些问题。所以我们第一步是对日志体系进行了升级。(在此之前我们完善了日志自身的基础能力,比如提升写入性能、提升日志压缩率、提升上传成功率、建立日志的数据大盘等等)



为了提高日志的排查效率,我们从日志内容着手,重新制定了端侧的标准日志协议。标准化的日志协议可以为我们在平台侧进行日志可视化建设、自动化日志分析提供帮助。我们从Log、Trace、Metric角度出发,依照手淘的实际情况将现有的日志分为以下几类:


  1. CodeLog: 兼容原有的日志,这些日志相对杂乱;

  2. PageLog:记录端上页面跳转情况,排查问题时可以从页面维度对日志进行划分;

  3. EventLog:记录端侧各种事件,比如前后台切换、网络状态、配置变更、异常、点击事件等等;

  4. MetricLog: 记录端侧运行时的各种指标数据,比如内存、CPU、业务的各种指标数据;

  5. SpanLog: 全链路日志数据。把各个独立的点串联起来,定义统一的性能度量、异常检测的标准。基于OpenTrace的方案和服务端打通,形成端到端的全链路排查机制。



有了这些数据之后。在平台侧配合日志可视化平台,可以对端侧的行为进行快速回放。得益于日志的标准化,可以从平台侧对日志进行分析,快速展示存在异常的节点。


端侧诊断升级


客户端是整个诊断体系的源头,一切的异常数据,运行信息都是由客户端上的各种工具进行收集上报的。目前端侧主要工具有:


  1. APM:收集端侧的各种运行、性能等信息,数据上报到服务端;

  2. TLOG:收集端侧运行时的日志信息,日志文件存放在本地,需要时服务端下发指令进行捞取;

  3. UT:端侧埋点工具,很多业务异常信息都会通过UT进行上报告警;

  4. 异常监控:这个以Crash SDK为代表,主要收集端侧的Crash信息,还有收集异常、用户舆情等相关的SDK;

  5. 排查工具:内存检测、卡顿检测、白屏检查等工具。这些没有直接归类在APM中,因为这些工具是采样运行,有的甚至默认是关闭状态。


可以看到端侧其实已经有不少成熟的工具在使用,但是在排查问题时候经常发现数据缺失等问题,主要原因在于一方面在平台侧这些数据比较分散,没有一个统一的接口进行查询;另一方面客户端没有对这些工具的数据做整合,发生异常时这些工具间少有交互,造成了数据缺失。



为了解决这些问题,我们在端侧引入了全新的诊断SDK和染色SDK。它们的主要功能有:


  1. 对接现有工具,收集端侧运行数据。把这些数据按照标准的日志协议写入到TLOG日志中;

  2. 监听端侧的变更信息,生成变更的染色标识;

  3. 监听端侧异常,异常发生时生成快照信息(包括运行信息、变更信息),上报服务端;

  4. 场景化诊断数据上报,根据服务端配置的规则,在特定场景进行数据收集和上报;

  5. 支持定向诊断,根据服务端下发的配置,调用对应的排查工具进行数据收集;

  6. 支持实时日志上传,针对特定用户和设备进行在线调试。


  异常快照


端侧的异常主要包括Crash、业务异常、舆情等。当异常发生时,上报的数据格式、内容、通道、平台都不一样。若想要增加一些数据,端侧和相应平台都需要进行改造。所以我们对端侧异常监控相关的SDK进行了监听,对于业务提供了异常通知接口。当诊断SDK接收到异常时,会利用当前收集到的运行信息生成一份快照数据。每个快照数据会有一个唯一的snapshotID。我们只需要把这个ID传递给对应的SDK,这样对现有的SDK改动是最小的。



快照数据随着端侧能力的加强也会越来越丰富。收集到的快照信息会上传到诊断平台,平台之间可以利用snapshotID进行数据关联。对于诊断平台来说,可以根据快照信息、日志信息对异常进行分析,给出初步的诊断结果。


  变更监控


手淘中大部分的问题是因为线上变更导致的。现有监控排查体系并没有专门对变更进行监控,主要还是依赖异常数量、异常趋势进行告警。这就有一定的滞后性,导致很难在放量阶段快速的发现问题。同时对于变更发布也没有一个统一的管控标准。所以我们在端侧引入了染色SDK来收集变更数据,配合无线运维的变更诊断平台,对变更发布进行监控,做到可灰度、可观测、可回滚。




目前端侧的变更包括通用的配置变更(Orange平台)、AB试验变更和业务自定义的变更(试金石、安全、新奥创等等)。染色SDK在端侧和这些SDK进行对接,收集到端侧的变更数据后会生成对应的染色标识并上报。配合TLOG和诊断SDK,记录这些变更,并且在发生异常时给异常信息打标。平台侧也会和各个发布平台、高可用数据平台打通,根据客户端上报的数据进行发布决策。



  • 染色标识


变更其实是服务端向客户端下发数据,客户端使用的过程。 




所以针对变更,我们定义出:


  1. 变更类型:用来区分变更的种类,比如配置变更(orange)、试验变更(ABTest)、业务A变更,业务B变更等等;

  2. 配置类型:一个变更类型下可能有多个配置,比如orange变更,每个配置有一个namespace,用来区分配置的类型;

  3. 版本信息: 代表了一个配置的一次具体的发布。不一定所有配置变更都有明确的版本信息,可以把某个发布或配置的唯一标识作为版本信息。比如每个orange配置发布都有一个version,每个ABTest发布都有一个publishID。


有了这些信息我们就可以给每一个变更生成一个唯一的染色标识。通过上报染色标识我们可以统计出变更的生效数;通过在快照信息中携带染色标识,可以计算有变更标识的crash率、舆情数量;通过和高可用大盘数据进行比较监控变更的质量。业务也可以在网络请求中带上染色标识,用于统计相关的接口是否存异常。


  • 灰度定义



对于染色SDK我们是希望在灰度期间可观测,提早发现问题,不把变更导致的问题带到线上全量环境中,所以我们把发布过程定位为三个阶段:


  1. 准备期:准备变更数据,预发验证、提交审批、线上发布。这个阶段可以确定发布变更的类型、配置、版本;

  2. 灰度期:对部分用户下发变更配置。我们的染色监控也主要是在这个阶段运行,主要为上报染色标识和在异常快照中携带染色标识。平台侧在这个阶段对数据进行处理,生成灰度相关数据;

  3. 全量期:当灰度达标之后,进入全量期。这个时候向所有满足条件的用户推送配置。


  数据上报控制


因为手淘用户量太大,变更全量之后如果还继续上报生效数据,对服务端的压力会很大。同时异常信息中如果继续打标意义也不大了。所以我们必须有一个机制来管控端侧的染色数据上报。


针对orange、ABTest这些通用的变更,我们进行了单独适配,可以根据实验号、配置namespace进行黑白名单控制、采样控制或发布状态来控制。但对于自定义变更来说,可控制的条件千差万别,如果要做到精细的控制就必须要理解这个特定的变更。所以我们定义了一些通用的条件:灰度标识、采样率、过期时间来控制。




这些信息是通过配置文件的形式下发到端上。端侧无需关注这些条件设置的逻辑,而是在平台侧进行设置,平台侧对接发布平台、高可用平台,并根据上报数据进行决策。目前主要还是依据配置中的灰度标识+超时时间来决定是否上报。


  发布门禁


端侧上报了生效数、异常染色等数据之后,服务端就可以根据这些数据来监控变更。根据相关Crash数量、舆情数量、灰度时间等来判定当前变更是否达到了全量发布的标准。 



同时也会列出和这次变更相关的crash信息、舆情信息。辅助判定本次变更发布是否存在风险。




目前已经有Orange配置变更、AB试验变更、详情、下单等业务接入。效果还是不错,已经成功规避了4个线上故障。 


  场景化上报


场景化数据上报,是诊断体系中的一个重要能力。以往都是当告警时我们手动的从端上捞取相关数据进行排查,并且不同异常需要的数据也不相同,经常要跨多个平台,进行多次操作。这就导致数据获取滞后,整个排查时长不可控。所以在端侧具备了新的日志标准、异常快照收集、异常变更染色等基础能力后,我们引入了场景化上报。



举个列子,按照现有的排查方式,当线上发生异常告警时,我们一般先通过上报的异常信息来排查,但受限于现有信息不全,往往还需要通过拉取TLOG来做进一步排查,然而TLOG捞取又依赖用户在线,这就导致整个排查定位时间非常长。 



引入场景化概念之后,当平台检测到异常数量快要达到阈值的时候,可以自动生成一份场景规则配置,圈选一批用户下发到端上。当端上发生了相同异常的时候,场景引擎会负责收集和上报所需要的数据,这样当告警达到阈值时平台上就已经有足够的数据进行分析定位。 


  • 场景规则


场景引擎主要用来执行服务端下发的场景规则,而一个场景规则主要由三部分构成:


触发(Trigger)


可以是端上的一个行为或一个事件。相对于以前只有在Crash、业务异常时才上报数据,我们对异常触发时机进行了扩充。


  1. 崩溃异常

  2. 用户截屏反馈

  3. 网络异常 (mtop错误、network错误等)

  4. 页面异常 (白屏、显示异常)

  5. 系统异常 (内存占用过高、 cpu占用过高、 耗电过快、发热、卡顿)

  6. 业务异常 (业务错误码、逻辑错误等)

  7. 启动 (一般用于定向诊断)


条件(Condition)


条件判定是整个场景化上传的核心。增加了场景条件之后,我们可以从多个维度更精准的去划分异常类型。条件大致上可以分为:


  1. 基础条件:从设备信息、用户信息、版本信息等维度去进行匹配和筛选;

  2. 状态条件:主要包括网络状态、当前页面、内存水位等运行时的信息;

  3. 特定条件:不同场景需要判定的条件是不同的。比如发生Carsh时,可以根据Exception类型、堆栈等信息进行匹配。而业务异常时可能根据错误码和网络错误来进行匹配。


行为(Action)


当端上某个规则被触发,并且满足设定的所有条件时,就会触发指定的行为,这样就可以根据不同的场景收集不同的数据。目前端侧主要行为有:


  1. 上传TLOG日志 

  2. 上传快照信息

  3. 上传内存信息

  4. 协同其他排查工具根据下发的参数进行数据收集上报


  • 场景下发




平台侧建立了一套新的场景管理平台,可以方便的配置各种场景和条件。并且也有标准的发布、审核、灰度流程。通过PUSH + PULL的方式,客户端可以及时的获取到场景规则。



平台和端侧也都支持定向下发配置的能力,通过指定一些基础的条件,可以针对不同设备,不同用户进行有针对性的场景下发。


  • 数据流量管控


端上匹配了对应的场景规则后,就会上报各种异常数据。但是如果数据量过大,会对服务端存储产生较大压力。所以我们针对场景上报的数据进行了流量管控。



从排查问题的角度出发,对于同一个问题我们可能只需要几份相关的日志和数据。所以我们在创建一个场景时会指定一个数据上报的阀值。当平台收集到足够的数据之后,这个场景就会停止,并通知客户端规则下线。


同时端上为了保证用户不因为频繁上传诊断数据而对正常使用造成影响,端侧也有自己的限流策略。比如必须是wifi环境才可以上报、限制每天执行规则的数量、限制每天上传的数据量、设定数据的上传间隔时间等等。


  • 自定义场景


目前我们的触发都是一些通用的场景,从高可用工具中获取数据上报。但是业务可能有一套自己的异常监控体系。所以我们也提供了相应的接口给业务来调用,利用我们场景下发、规则表达式执行、获取运行数据等能力,来帮助业务进行问题诊断。业务可以定义自己的触发时机、触发条件。后续我们也可以加入自定义行为的能力,让业务也可以根据场景来上报相应的数据。


  • 定向诊断


端上目前除了TLOG,还有内存工具、性能工具、卡顿工具等其他一些排查工具。这些工具在排查特定问题时比较有用。但目前在线上都是通过配置采样开启或默认关闭的。而现有的配置还无法针对设备,用户进行定向下发。这就会导致排查问题时拿不到完整有效的信息。所以我们也是利用场景化定向下发能力,对现有工具进行了简单的改造,协同这些工具进行异常数据的收集和上报。


未来展望


目前端侧的诊断能力还在持续的建设中,我们也针对现有排查过程中存在的痛点进行迭代,比如实时日志、远程调试、完善全链路数据、异常数据等等。此外,我们也需要看到,端侧诊断不再是简单的堆砌工具,收集数据,我们未来还需要更有针对性、更精细化的去收集和处理数据。 



而随着诊断数据的完善,下个挑战将是平台如何利用数据进行问题根因定位、分析问题影响面、对诊断结果进行沉淀。对于端侧而言,也不仅仅只定位在数据收集,还可以依赖平台的诊断知识沉淀,结合端智能的能力,在端侧实现问题诊断的能力。同时可以配合端侧的降级能力、动态修复等能力,在发生异常后实现自愈。


✿  拓展阅读

作者|伝逸
编辑|橙子君
出品|阿里巴巴新零售淘系技术

推荐阅读