在解决iOS应用线上崩溃时,我们通常要分析崩溃日志来定位原因。线上崩溃日志一般是未符号或部分符号化的日志,是一堆十六进制的内存地址集合,可读性比较差,这对解决问题几乎没有帮助。所以,我们首先需要先对崩溃日志进行符号化——根据App出错的函数内存地址,在.dSYM文件中找到具体的文件名、函数名和行号信息。有了上述信息,我们就可以定位分析具体的崩溃原因了。

如果存在大量的崩溃日志,光符号化崩溃日志是远远不够的,我们不可能一条一条去分析大量崩溃日志,这时候就需要对符号化的崩溃日志进行聚类了。通过聚类,将相同或相近的一类崩溃归类在一起,进行统计分析,这在实际问题解决中具有重要的意义。本文将介绍基于NLP的崩溃日志聚类的实现。

本文提纲如下:

1. 崩溃符号化

1.1 崩溃日志结构

线上崩溃日志结构大致如下图所示。我们需要关心的信息主要是标注为红色的部分,具体说明详见表格的描述。

图1.1 崩溃日志片段
日志段 字段 意义
 头部信息 Identifier 应用的bundle ID
Version 应用版本号
Code Type 设备CPU类型,例如ARM-64
Date/Time 崩溃时间
OS Version 崩溃设备及系统版本
异常信息 Exception Type 崩溃类型
Exception Codes 崩溃代码
Crashed Thread 崩溃线程号,根据线程号定位到具体的崩溃栈信息
崩溃栈 Thread xx: 线程信息
Thread xx Crashed 实际崩溃线程栈信息,也是符号化的关键信息
崩溃线程状态 Thread xx crashed with ARM-64 Thread State 崩溃线程状态信息
Binary Images yourAppProjectName 你的工程名称
<xxxxxxxxxxxxxxxx> 崩溃日志对应的dsYM文件的uuid,日志和dsYM的uuid要一一对应才可以符号化

通过分析崩溃日志的格式,我们很容易获取到应用的bundle ID、版本号、CPU类型、崩溃时间、崩溃设备及系统版本、崩溃类型、崩溃线程号,崩溃线程栈信息、崩溃日志对应dsYM文件的uuid。了解这些基础信息,我们就可以进行符号化了。

1.2 符号化方法

Xcode自带工具可以帮助我们来完成符号化的工作:symbolicatecrash、atos。

1.2.1 symbolicatecrash

   symbolicatecrash是一个将堆栈地址符号化的脚本,执行symbolicatecrash命令,可以得到一个符号化之后的输出文件,查看这个文件可以看到崩溃的位置。

1)准备工作

准备3个文件,放在同一个文件夹下

I.  dSYM文件;
II. 崩溃日志文件(注意文件格式为.crash,如果是其他格式,如txt,先将文件后缀改为.crash);
III.symbolicatecrash(symbolicatecrash的位置可以通过下面的指令来查找)

find /Applications/Xcode.app -name symbolicatecrash -type f

会输出所有的路径,我们只需要随便拷贝一个脚本和dSYM、崩溃日志放在一起即可。

find: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/private/var/mobile: Permission denied

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/iOSSupport/Library/PrivateFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash

/Applications/Xcode.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/Library/PrivateFrameworks/DVTFoundation.framework/symbolicatecrash

/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/Library/PrivateFrameworks/DVTFoundation.framework/symbolicatecrash

/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/DVTFoundation.framework/symbolicatecrash

/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash

2)执行命令

在终端分别输入下面的两条命令,会生成YourApp.log文件,在该文件中可以产看具体的崩溃位置。

export DEVELOPER_DIR="/Applications/XCode.app/Contents/Developer"

./symbolicatecrash YourApp.crash YourApp.app.dSYM > YourApp.log

1.2.2 atos

   atos命令的特点是可以对单行堆栈进行符号化操作,通过输入本地地址(load address)和崩溃内存地址(address to symbolicate)就可以符号化。

1)命令使用

atos -arch <Binary Architecture> -o <Path to dSYM file>/Contents/Resources/DWARF/<binary image name> -l <load address> <address to symbolicate>

Binary Architecture:arm64、armv6、armv7armv7s, 根据应用的情况来写;

Path to dSYM file: dSYM文件的路径;

binary image name: 你工程的名字;

load address:基地址,如果我们的崩溃日志中没有这个信息,load address = address to symbolicate - offset;

address to symbolicate:当前方法的内存地址。

2)使用例子

参考图1.1的崩溃日志片段,我们通过顶部的崩溃信息找到崩溃线程的ID为23,然后查看线程号为23的崩溃栈信息,从圈红色部分找到本地地址和崩溃的内存地址。例如本地地址为:0x102104000,崩溃的内存地址:0x000000010338cee8。

图1.2 崩溃线程信息

执行指令即可符号化出崩溃日志。

atos -o yourProject.app.dSYM/Contents/Resources/DWARF/yourProjectName -arch arm64 -l 0x102104000 0x00000001032c60a4

1.2.3 符号化方法总结

symbolicatecrash:开发者不需要分析本地地址和崩溃内存地址,直接将整个崩溃文件符号化,指令会自动找到崩溃线程栈,并对崩溃关键信息进行符号化,操作简单

atos:需要开发者分析本地地址和崩溃内存地址才能进行符号化,优点是可以对单行堆栈进行符号化。

在实际应用中,我们需要根据项目线上崩溃情况,灵活选择符号化的方法。例如在博主的项目中,下载的崩溃日志是已经格式化的csv崩溃日志,采用atos来符号化,便于批量操作,统计分析。

2.崩溃日志聚类

通过第1节内容,我们已经可以将线上大量的崩溃日志进行符号化了。实际项目中,光符号化崩溃日志远远不够的。面对大量的崩溃日志,我们不可能一条一条地去分析。因此,对符号化的崩溃日志进行分门别类,将相同或相近的一类崩溃归类在一起,统计分析每一类崩溃,在应用问题解决中十分有意义。本节将介绍基于NLP的崩溃日志聚类实现。

2.1 聚类流程

整个聚类过程分为崩溃日志输入、分词、特征提取、输出特征向量、计算相似度、聚类归并、输出统计结果七部分。

图2.1 聚类过程

2.2 聚类实现

1)崩溃日志输入:就是批量输入符号化的崩溃日志,初始化每条崩溃版本号、标题、崩溃log、崩溃次数等。

2)分词:采用jieba分词库,对崩溃log进行分词。

3)特征提取:将分词后的字符串作为每条崩溃 log的特征。

def getWordList(s):cut = jieba.cut(s)list_word = (','.join(cut)).split(',')return list_word

4)生成特征向量:循环计算每两条日志的所有词、取并集、计算词频。

def getWordVector(list_word1, list_word2):# 列出所有的词,取并集key_word = list(set(list_word1 + list_word2))# 给定形状和类型的用0填充的矩阵存储向量word_vector1 = np.zeros(len(key_word))word_vector2 = np.zeros(len(key_word))# 计算词频# 依次确定向量的每个位置的值for i in range(len(key_word)):# 遍历key_word中每个词在句子中的出现次数for j in range(len(list_word1)):if key_word[i] == list_word1[j]:word_vector1[i] += 1for k in range(len(list_word2)):if key_word[i] == list_word2[k]:word_vector2[i] += 1return word_vector1, word_vector2

5)计算相似度:余弦距离是自然语言处理中用来计算两个句子的相似度的方法之一,在本文中,博主通过计算特征向量的余弦距离来判断两条日志的相似度。余弦距离越大,相似度越大。

def calcuCosDistance(vec1, vec2):dist = float(np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2)))return dist

6)聚类归并:设定余弦距离阈值,当相似度大于等于余弦阈值时,则认为这两条日志是相似的,把它们归并在一起。余弦阈值选取多少,没有统一的标准,需要在项目中进行测试选择一个合适的值。

7)输出统计结果:遍历聚类归并全部崩溃日志之后,输出统计后的崩溃日志,例如保存到数据库或以csv格式输出。 下面是博主项目中输出的统计结果截图。

图2.2 崩溃日志聚类结果截图

3.参考文章

1.Apple Developer Documentation

2.jieba:https://github.com/fxsjy/jieba

iOS崩溃日志符号化及NLP聚类实现相关推荐

  1. iOS崩溃日志符号化 UUID获取

    1. 符号表是什么? 符号表就是指在Xcode项目编译后,在编译生成的二进制文件.app的同级目录下生成的同名的.dSYM文件. .dSYM文件其实是一个目录,在子目录中包含了一个16进制的保存函数地 ...

  2. iOS 崩溃日志在线符号化实践

    1. 什么是符号化? 在日常开发中,应用难免会发生崩溃.通常,我们直接从用户导出来的崩溃日志都是未符号化或者部分符号化的,都是一堆十六进制内存地址的集合,可读性较差.未符号化或者部分符号化的崩溃日志对 ...

  3. iOS崩溃日志分析-b

    1名词解释 1.1. UUID 一个字符串,在iOS上每个可执行文件或库文件都包含至少一个UUID,目的是为了唯一识别这个文件. 1.2. dwarfdump 苹果提供的命令行工具,其中一些功能就是查 ...

  4. ios崩溃日志收集_iOS崩溃与日志分析

    在iOS开发中经常需要靠记录日志来调试应用程序.解决崩溃问题等,整理常用的日志输出和崩溃日志分析. 最新更新:2018-11-30 基于CocoaLumberjack 的 Swift使用封装库 一.崩 ...

  5. iOS崩溃日志的分析

    崩溃日志的产生 iOS中运行App过程中如果发生程序崩溃,会生成一个崩溃日志文件.这个文件会保存的特定系统目录下,扩展名是crash.当手机连接到iTunes时,会将该文件同步到电脑上. 在Mac系统 ...

  6. 如何看iOS崩溃日志

    重点:Triggered by Thread这句话后边的线程号,快速定位问题出现在那个线程,是否是你的锅:Triggered by Thread所指的线程表示导致异常.崩溃的线程 下边内容转自简书 简 ...

  7. ios崩溃日志收集_漫谈iOS Crash收集框架

    为了能够第一时间发现程序问题,应用程序需要实现自己的崩溃日志收集服务,成熟的开源项目很多,如 KSCrash,plcrashreporter,CrashKit 等.追求方便省心,对于保密性要求不高的程 ...

  8. 遭遇Crash文件战:教你如何搞定iOS崩溃日志

    请叫我背景 最近在提交应用到App Store的时候,竟然被拒了两次.那时候心里的想法是,尼玛完蛋了,要被老板开除了,我是不是要失业了.于是乎那两周几乎毛脑子都是为什么Apple你这么狠心,我们明明相 ...

  9. iOS应用崩溃日志分析 iOS应用崩溃日志揭秘

    转自:http://www.raywenderlich.com/zh-hans/30818/ios%E5%BA%94%E7%94%A8%E5%B4%A9%E6%BA%83%E6%97%A5%E5%BF ...

最新文章

  1. 我们需要什么样的数据架构?
  2. Jenkins持续集成环境之插件管理和角色管理
  3. ADO.NET知识要点
  4. 阿里云ARMS重磅推出小程序监控,助力小程序稳定运行
  5. 数据仓库中的模型设计(转)
  6. web 折线图大数据量拉取展示方案_分布式、服务化的企业级 ERP 系统架构设计方案...
  7. [C] 跨平台使用Intrinsic函数范例2——使用SSE2、AVX指令集 处理 双精度浮点数组求和...
  8. 计算机办公软件考证教学总结,考证经历——办公软件的套路
  9. linux运行uclinux程序,uClinux的编译与运行详解
  10. cs6制作拼图游戏 dreamweaver_Dreamweaver制作拼图步骤
  11. 8.22 ps课堂练习
  12. 拼多多直播带货,中小主播及商家的新机会
  13. 投影仪用光学引擎行业现状调研及趋势分析报告
  14. JavaScript实现存款利息计算器
  15. 计算机视觉图像处理入门
  16. 求二叉树根节点到叶节点的所有路径
  17. Linux 监控工具 tsar(转)
  18. ArcGIS中的TIN与DEM数据的生成
  19. int和String类型的转换
  20. js:图片url转base64编码

热门文章

  1. 有关clipToPadding、 clipChildren的那些事
  2. 打造3大产品差异化,成就下一个亚马逊爆品!
  3. C++基础知识(常函数和常对象)
  4. 利用 pinyin4j 把汉字转化为拼音
  5. 虚拟相机IOS手机端安装教程
  6. 莆系如何投放快手广告?
  7. 电脑老是显示无网络连接到服务器,电脑怎么老弹出无法与服务器建立连接
  8. 黑苹果简单的手动开启显示器HiDPI教程
  9. 自行更换iPhone 6s 手机电池 | 工序步骤
  10. 链表(提高)-数据结构(二)