GTLC全球技术领导力峰会·上海站,首批讲师正式上线! 了解详情
写点什么

闲鱼如何建设技术舆情治理体系

2021 年 3 月 14 日

闲鱼如何建设技术舆情治理体系

现状和问题

null

闲鱼的舆情治理,依托阿里集团的设施建设,具备以下能力:

  • 崩溃异常、性能在线聚合查询;

  • 本地日志:TLog

  • 在线日志:埋点日志(t+1)和用户行为日志(路径和请求)


但在应对舆情治理方面仍存在较多的问题:

  • 有相当一部分闪退、黑屏、卡死舆情无 Crash 或 ANR 日志;

  • 技术舆情中的业务问题定位困难;

  • 业务问题如图片视频上传失败、内容显示异常、无法退出、服务器错误等;

  • 日志内容缺失:大部分业务日志被写入控制台,而不是本地日志或在线日志;

  • 个别重要业务使用埋点日志,但仍可能存在内容不足和 t+1 不及时问题。

  • 本地日志定位问题能力有限

  • 本地 TLog 日志有较为详细的集团二方 SDK 日志,但缺失设备基础信息、业务日志、用户行为日志等

  • 未知异常问题,如视频绿屏等,无控制台 logcat 日志

  • 日志规范不完善,日志查看效率低

  • 本地日志回捞困难

  • 用户主动反馈时,没有触发本地日志上报

  • 闲鱼属于交易 App,用户不会长时间在线,在线命令推送成功率低

  • 命令推送在后台没有缓存机制

  • 反馈问题和线上实际情况存在偏差

  • 闲鱼反馈入口较深,相比闲鱼上亿用户基数,反馈占比低,存在线上有问题但无反馈的情况

舆情治理方案整体设计

基于现状问题,重新梳理和补充的舆情治理体系如下图:


null


线上舆情问题治理体系


下面会重点展开讲述的内容:

  • 如何提升本地日志定位能力

  • 补充线上卡顿监测能力

  • 补充主动发现问题能力

提升本地日志定位能力

本地控制台日志补充

治理前期,大量业务日志进入了控制台日志,即便治理后将大量日志转入 tlog 日志,仍有部分日志流入控制台,如 Android Maven 引入独立模块和 Flutter 插件包模块。此外,部分未知异常问题,如视频绿屏、黑屏等,logcat 日志也提供了定位的可能性。


Android Log 模块提供了多种日志缓存类型,见 Android logging[1],可通过 logcat 命令获取对应类型的日志。这里,我们在用户反馈的时候,分别将 LOG_ID_MAINLOG_ID_EVENTS 和 LOG_ID_CRASH 类型 logcat 读取并写入到本地文件,而后将 logcat 日志同 tlog 文件一起打包通过 AUS 上传至 OSS。


// LOG_ID_MAIN 主应用程序log,-t 设置日志上限 20000adb logcat -d -v threadtime -t 20000
// LOG_ID_EVENTS 系统事件信息adb logcat -d -b events -v threadtime -t 6666
// LOG_ID_CRASH 应用程序 crash 日志adb logcat -d -b crash -v threadtime -t 6666
复制代码


null


logcat.txt 内容

本地日志回捞能力

前面提到,由于在线命令推送成功率低且后台无命令缓存机制,所以闲鱼 App 本地日志回捞困难。为解决日志难以获取问题,舆情治理体系中设计了多种日志回捞策略,见下图所示。


null


本地日志回捞策略


null


本地日志下载查看流程


  • 为提升用户主动反馈触发的日志上传成功率,使用 AUS 上传日志打包文件至 OSS 平台,同时将 url 写入反馈内容(打包和上传若超出 5 秒则无法写入反馈内容)和阿里云 SLS 实时日志平台;

  • 为提升研发下载本地日志的效率,使用 TLog SDK 上传至 TLog 平台,其中 50% 以上能上传成功。

线上卡顿/ANR 检测能力

线上用户反馈 ANR 并给出截图证明,因为没有卡顿日志,难以定位问题。


null


线上用户反馈黑屏,无有效日志难以定位问题


页面卡死的另一种表现

技术方案现状

在闲鱼 App 的混合工程场景,依托 Emas 平台已实现 iOS 端卡顿检测,Flutter 端卡顿检测方案查看 Flutter 卡顿问题的监控与思考[2],这节主要讲述 Android 端线上卡顿/ANR 检测。

在线下场景,Android 端卡顿/ANR 检测手段已经很成熟,普通卡顿检测方案有 BlockCanary[3],ANR 检测可通过 adb bugreport 查看 traces.txt 文件得到。然而在线上环境,以上卡顿检测方案就存在一定问题。

traces.txt 文件权限问题

在线上场景,为了监听识别是否发生 ANR 以及读取 ANR 内容,APP 需要监听 traces.txt 文件变化,并尝试读取 traces.txt 文件内容。监听文件的方案,在 Android 6.0 及以后存在权限问题,大部分场景无法检测到 ANR


  • 无法访问 /data/anr/traces.txt 文件

  • 无法读取有效系统属性 dalvik.vm.stack-trace-file


如以下代码执行在红米手机 Android 11 上运行,mSystemTraceFilePath 为 "",mSystemTraceFile 的路径为 "/"


File mSystemTraceFile;
...this.mSystemTraceFilePath = "/data/anr/traces.txt";this.mSystemTraceFile = new File(this.mSystemTraceFilePath);if (!this.mSystemTraceFile.exists()) { String propSystemTraceFilePath = SystemPropertiesUtils.get("dalvik.vm.stack-trace-file"); ... this.mSystemTraceFile = new File(propSystemTraceFilePath); ...}...
复制代码

BlockCanary 检测原理和性能问题

核心原理



BlockCanary 检测 500ms 卡顿


BlockCanary 的核心原理是,设置 UI 线程的 Looper.mLogging 字段,主线程每次处理消息均会执行 print 方法。


public void start() {    if (!mMonitorStarted) {        mMonitorStarted = true;        Looper.getMainLooper().setMessageLogging(mBlockCanaryCore.monitor);    }}
复制代码

BlockCanary.java[4]


public void setMessageLogging(@Nullable Printer printer) {    mLogging = printer;}
public static void loop() { ... for (;;) { ... // This must be in a local variable, in case a UI event sets the logger final Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } ... }}
复制代码


Looper.java


在 print 方法中时,触发 StackSampler 工作,即取消上一次异步线程延迟任务,重新触发一次延迟任务,延迟时间为 BlockThreshold * 0.8f (假设要检测 500ms 以上的卡顿堆栈,则延迟时间为 400ms)。若 UI Looper 任务发生卡顿(>BlockThreshold),则延迟任务被执行,且在卡顿期间的获取主线程堆栈信息,之后在下一次 print 方法被执行的时候,若确认发生卡顿,则可把主线程堆栈信息当做卡顿堆栈记录上报。


@Overridepublic void println(String x) {    ...    if (!mPrintingStarted) {        mStartTimestamp = System.currentTimeMillis();        mStartThreadTimestamp = SystemClock.currentThreadTimeMillis();        mPrintingStarted = true;        startDump();    } else {        final long endTime = System.currentTimeMillis();        mPrintingStarted = false;        if (isBlock(endTime)) {            notifyBlockEvent(endTime);        }        stopDump();    }}
复制代码


LooperMonitor.java[5]

性能问题

在线上环境,大部分场景下并不会发生卡顿,但卡顿检测 SDK 会一直执行。可以发现 app 每一帧时间(16.6ms),UI Looper 中的任务会执行多次,最终产生大量的无效字符串拼接操作大量小对象碎片。特别的,在线上低端机或者 cpu 负载较高的场景下,app 性能会因此降低,影响用户体感。


logging.println(">>>>> Dispatching to " + msg.target + " " +                    msg.callback + ": " + msg.what);
复制代码

卡顿检测方案

方案设计

针对 traces.txt 读取权限问题,可通过检测主线程 5s 卡顿当做 anr。针对 BlockCanary 线上使用的性能问题,为降低延迟任务取消和触发频率,同时避免字符串对象频繁创建问题,必须放弃 Looper.mLogging 的方案。重新思考为什么可以通过设置 Looper.mLogging 检测卡顿?其满足 2 个条件:

  • 若主线程方法执行发生卡顿,则 Looper Task 执行时长变长

  • 可通过 Looper.mLogging 监听每个 Task 执行时长


闲鱼线上使用 Android 帧回调代替 Looper Task 方案,同时满足以上 2 个条件:

  • 若主线程方法执行发生卡顿,则帧回调间隔时长变长

  • 可通过注册帧回调监听每帧时长

此外,为避免 BlockCanary 方案延迟任务触发和取消的频率过高的问题,仅在帧回调处记录时间戳,不再取消延迟任务,但在延迟任务执行时判断是否发生卡顿,同时记录主线程堆栈。

假设 500ms 以上为卡顿,整体方案流程图如下:

  • 无卡顿场景


null


  • 卡顿场景


null


  • 仅在频繁触发的帧回调处,记录时间戳,无性能消耗

  • 避免延迟任务触发和取消的频率过高的问题,500ms(卡顿阈值) 最多执行 2 次延迟任务

  • 不再取消延迟任务

  • 在任务执行时,判断当前时间和上一帧时间戳时间差。仅在发生卡顿时,dump 主线程堆栈

定义 5s 以上卡顿为 ANR,为检测 ANR,同样通过 500ms 卡顿检测,并做卡顿堆栈聚合,当连续发生卡顿大于 5s 且堆栈信息不变,则认为发生 ANR。发生 ANR 时,记录当前设备 CPU 负载等信息。

检测效果

闲鱼首页卡片点击事件中故意制造 500ms 和 5s 卡顿查看卡顿检测结果。


// CardView61801.java
private void doOnClick(String redirectUrl, Map<String, String> trackParams) { if (null == mCardBean) return;
try { Thread.sleep(500); // Thread.sleep(5000); } catch (Exception e) { e.printStackTrace(); } ...}
复制代码


查看检测结果

  • Sleep 500ms



  • Sleep 5s



小结

以上是闲鱼 Android 线上卡顿检测方案,线上已经运行超过 3 个版本,通过日志可发现用户反馈卡死、无反应、闪退、黑屏等现象都有可能是 ANR 造成。整体方案有以下特点:


  • 线上卡顿检测无性能问题

  • 以 5s 以上卡顿当做 ANR

  • 相比 BlockCanary Looper Task 在 0.8*卡顿阈值 时获取卡顿堆栈,本方案 500ms 卡顿检测有更高概率获取错误堆栈。但通过连续卡顿堆栈比对,可确保 5s 卡顿堆栈的准确性。而 500ms 卡顿通过线上统计提升准确性

  • 若业务需要,必须提升 500ms 单次卡顿堆栈准确率,可简单修改方案:判断大于 250ms 获取一次卡顿堆栈,2 次连续相同卡顿堆栈且卡顿时长大于 500ms 作为最终卡顿判断

主动发现问题能力

由于闲鱼 App 反馈入口较深,因此相比上亿用户而言,每日技术舆情反馈量占比偏低,以此可知技术舆情反馈量并不能准确反应线上质量情况。为此,我们通过监控埋点构建线上关键舆情问题和基础性能大盘,同时通过监控大盘主动发现线上重点待解决问题,加速线上舆情收敛速度和质量提升,流程图如下所示。


null


主动发现问题流程图

监控大盘


null


主动发现问题大盘示例

  • 业务舆情问题大盘

通过统计一段时间的舆情问题,得到关键舆情问题,以此添加监控埋点并构建线上报表。通过大盘数据得到线上问题发生量和重要归因,通过重点解决排名前几的归因,达到舆情问题快速收敛的目的。


  • 基础问题

除了 Crash、Flutter 异常、性能等线上大盘,我们构建了 5s 卡顿监控、网络请求失败、慢请求、错误 toast 等基础监控大盘。

监控问题定位

基于大盘发现了问题,需要获取对应日志来定位问题,但问题对应的用户很可能并不会反馈舆情或反馈内容不是该问题,为此我们构建了实时日志查询以及本地日志批量回捞能力。

实时日志查询平台


null


自建舆情追踪平台

针对关键监控问题,客户端增加对应的 SLS 实时日志,在自建舆情追踪平台获取用户的在线日志。平台支持用户名和时间查询,同时支持用户行为、用户异常、舆情日志类型的组合查询。

本地日志批量回捞能力

在线日志难以避免日志内容不足的问题,如基础日志、其他关键模块日志等,然而单个用户的本地日志回捞成功很低(原因见上文内容),为此构建舆情日志回捞平台,通过批量回捞的方式确保能获取到舆情问题某个用户的本地全量日志。

  • 输入舆情 IssueName 查询用户 id


null


null


  • 批量回捞结果查询


null

总结和展望

经过治理,整体线上技术类舆情占比从 10.5% 降低至 4.7%;基于主动发现问题和解决重点问题,每日上传图片失败数从 10W+ 次降低至小于 7K+ 次,其他数据不再罗列。

初步建立的闲鱼舆情治理体系如下所示:


  • 日志类型:本地日志和在线日志;

  • 在线日志:实时在线 SLS 日志,用户行为日志,埋点(t+1)日志,高可用 SDK 日志(崩溃异常、白屏、性能);

  • 日志查询:提供日志规范和日志过滤文档提供查询效率;

  • 日志内容:基础日志和业务日志;

  • 基础日志:logcat 日志,卡顿/ANR 日志,高可用 SDK 日志(crash、异常等),设备信息、账号信息等;

  • 日志回捞:反馈时主动上传(TLog 平台和 OSS 平台),在线命令回捞(含 TLog 平台回捞,自建消息通道回捞);

  • 问题发现:用户反馈问题和主动发现问题

  • 反馈入口:普通客服反馈和灰度截屏反馈

  • 特别的,MIUI 系统下的截屏事件可监听广播 miui.intent.TAKE_SCREENSHOT


此外,未来仍有很大的演进空间如下:

  • 日志可视化

  • 日志语义化描述展示

  • 用户行为、内存、CPU、流量等可视化


null


闲鱼用户本地日志手动解析后的内存可视化举例


  • 日志智能解析

  • 关键日志和历史问题关联形成知识库

  • 关键日志反向回捞用户日志

  • 类似主动发现问题场景中的回捞能力,可根据配置下发或其他关键在线日志回捞用户日志

  • 日志关联聚合查询

  • 基于用户和时间,聚合服务端、前端、客户端日志,聚合多种在线和本地日志。

References

[1] Android logging: https://developer.android.com/ndk/reference/group/logging#group___logging_1ggabcd142e91968af61158b3d0b72eb72dfaec4d00613b6ed282851bf7af5ca24e33

[2] Flutter 卡顿问题的监控与思考: https://zhuanlan.zhihu.com/p/148985175

[3] BlockCanary: https://github.com/markzhai/AndroidPerformanceMonitor

[4] BlockCanary.java: https://github.com/markzhai/AndroidPerformanceMonitor/blob/master/blockcanary-android/src/main/java/com/github/moduth/blockcanary/BlockCanary.java

[5] LooperMonitor.java: https://github.com/markzhai/AndroidPerformanceMonitor/blob/master/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/LooperMonitor.java


本文转载自:闲鱼技术(ID:XYtech_Alibaba)

原文链接:闲鱼如何建设技术舆情治理体系 (多图多代码)

2021 年 3 月 14 日 13:001474

评论

发布
暂无评论
发现更多内容

简单了解InnoDB底层原理

SH的全栈笔记

MySQL 数据库 innodb

浅谈JVM和垃圾回收

SH的全栈笔记

Java JVM JVM虚拟机原理 垃圾回收算法

浅谈在探索数分之路上的“数据思维”论述

小飞象@木木自由

数据分析 数据分析体系 数据思维 数据分析方法论

NIST发布酒店业网络安全指南

Machine Gun

网络安全 信息安全 WEB安全

架构实战营 模块2 课后作业

༺NPE༻

一种提升流媒体服务DSS的IO并发性能方案

Changing Lin

签约计划 四月日更

【提纲】专访融云CTO杨攀 | 技术型人才的自我修炼

Python测试开发

调查采访能力考核

为什么微服务一定要有 API 网关?

xcbeyond

微服务 api 网关 4月日更

为什么我愿意持续做这样一件看似没有价值的事情

leoay

坚持 持续写作 长期价值

直击灵魂!阿里技术官甩出内部爆款性能优化实战笔记,理论实战一键搞定!

Java王路飞

Java spring 程序员 架构 面试

Lombok初始使用及遇到的问题

风翱

lombok 【4 月日更】

对话声网 Agora 首席科学家钟声 :声网的未来规划和人才建议

小诚信驿站

采访 调查采访能力考核

融合趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

Apache Flink

flink

使用Agora SDK开发React Native视频通话App

声网Agora

RTC React Native 声网 RTE

Excelize 2.4.0 正式版发布, 新增 152 项公式函数支持

xuri

GitHub Excel 开源项目 Go 语言 Excelize

朱嘉明:算力产业正面临着一个十年的长周期

CECBC区块链专委会

数字经济

关于数字人民币、加密货币,央行前行长周小川、副行长李波博鳌论坛发声

CECBC区块链专委会

数字货币

如何从零开始学Python:(3)划重点:使用IDLE创建列表时需要注意的地方

广之巅

Python 四月日更

推进智慧城市建设 博睿数据亮相长三角城市数字化转型高峰论坛

博睿数据

数字化转型高峰论坛

面试4轮字节Java研发岗,最终拿下Offer(原题复盘)

码农之家

编程 程序员 互联网 面试 字节

python 变量作用域和列表

若尘

变量 Python编程 作用域

Python 爬虫实战(一) 爬取自如网租房信息

U+2647

python 爬虫 四月日更

深入理解Java虚拟机-HotSpot

华章IT

Java JVM 虚拟机

百度大脑3月新品推荐:EasyDL视频目标追踪全新发布

百度大脑

百度大脑 EasyDL

翻译:《实用的Python编程》09_03_Distribution

codists

Python

奇绩创坛2021秋季创业营开始报名

奇绩创坛

【AI全栈二】视频流多目标多类别无延迟高精度高召回目标追踪

cv君

人工智能 AI 目标检测 视频跟踪 综述

方寸之间,书写天地

石云升

4月日更 1 周年盛典 我和写作平台的故事 InfoQ 写作平台 1 周年

IPFS矿机投资靠谱吗?IPFS挖矿可靠吗?

投资矿机v:IPFS1234

IPFS矿机投资靠谱吗 IPFS挖矿可靠吗

斗智亦斗棋,零售云市场的“楚河汉界”突围赛

脑极体

精通比特币:为什么它对自由、财务和未来至关重要(上篇)

CECBC区块链专委会

比特币

DNSPod与开源应用专场

DNSPod与开源应用专场

闲鱼如何建设技术舆情治理体系 -InfoQ