开端
开发中触摸的除了代码以外,最多的可能便是日志的。 像Android日志检查,最简略的便是这样:
adb logcat
然后体系日志就会连绵不断的在控制台输出,其中包括了各种咱们关心的重要的调试信息。 可是这仅仅一种合适开发调试的检查方式,有没有其他方法呢。
答案是必定的,现在应用商店供给了一些自动化测验,对测验失利的设备可能会供给一些体系日志,失利的原因可能是安装失利、运转时溃散、ANR等等,有没有想过这些日志是怎样生成的呢,关于测验小伙伴怎样在测验设备上搜集体系日志呢,下面就介绍一种 android 内置的日志搜集办法。
搜集陈述
好在 android 交心的供给了一个东西 bugreport ,Android 的所有版本都支撑经过 adb获取 bug 陈述, 所以怎样运用呢: 假设发现应用呈现了溃散等反常情况时,不要紧张手机连接电脑,输入指令(这里不对 adb 环境的做介绍,后边有下载链接)
adb bugreport
静静等待陈述生成并导出,结束后会有如下输出,会有一个zip包在当前途径下生成
咱们能够直接解压这个zip来翻开 这里只标识了一些重要的文件意义,其他的无法直接检查,需求凭借到GUI东西,后边会介绍
其中最重要的便是 bugreport-meizu_18X_CN-RKQ1.210614.002-2022-12-07-11-11-54.txt,命名格式为bugrepory_<brand>_<model>_<版本号>-<yyyy-MM-dd-HH-mm-ss>.txt
,里边包括了咱们想要看的体系日志信息,还有电池、CPU、内存、内核日志、ANR等等信息,后边会对这些进行介绍。
这样咱们的日志信息就导出来了,如果日志比较少,咱们能够直接这个txt文件查阅,不过通常情况下这个文件都是比较大的,动辄几十十几M,直接检查显然不太便利,下面介绍两个GUI东西来协助咱们检查它。
检查陈述
下面是Android 官方的介绍文档,里边包括了对日志文件的结构有具体的介绍,点击下面地址到官方具体介绍
阅读 bug 陈述
任何类型的开发工作,bug 都在所难免,而 bug 陈述关于找出和解决问题至关重要。Android 的所有版本都支撑经过 adb获取 bug 陈述;Android 4.2 及更高版本供给了一个开发者选项,供开发者获取 bug 陈述并经过电子邮件、云端硬盘等分享陈述。
Android 过错陈述中包括文本 (.txt) 格式的 dumpsys
、dumpstate
和 logcat
数据,便于您轻松查找特定内容。以下各部分具体说明了 bug 陈述的组成部分,介绍了常见问题,并供给了一些实用提示和 grep
指令,用于查找与 bug 相关的日志。大多数部分中还包括 grep
指令及输出或 dumpsys
输出方面的示例。
翻开 bugreport-meizu_18X_CN-RKQ1.210614.002-2022-12-07-11-11-54.txt 文件,这里了解一下它的主要内容。
Logcat 检查
system 部分专门用于记载框架方面的信息,与包括所有其他内容的 main 部分比较,该部分包括更长时间内的记载
------ SYSTEM LOG (logcat -v threadtime -v printable -v uid -d *:v) ------
--------- beginning of system
12-07 11:11:55.416 1000 621 621 E SELinux : avc: denied { find } for pid=30140 uid=10185 name=tethering scontext=u:r:permissioncontroller_app:s0:c185,c256,c512,c768 tcontext=u:object_r:tethering_service:s0 tclass=service_manager permissive=0
------ 0.128s was the duration of 'SYSTEM LOG' ------
事情日志
------ EVENT LOG (logcat -b events -v threadtime -v printable -v uid -d *:v) ------
--------- beginning of events
12-07 10:58:48.732 1000 621 621 I chatty : uid=1000(system) /system/bin/servicemanager expire 13 lines
12-07 10:58:48.934 1000 621 621 I auditd : avc: denied { find } for pid=30140 uid=10185 name=tethering scontext=u:r:permissioncontroller_app:s0:c185,c256,c512,c768 tcontext=u:object_r:tethering_service:s0 tclass=service_manager permissive=0
------ 0.062s was the duration of 'EVENT LOG' ------
这里只介绍这两种常用的日志部分,实际上它还包括了 stat log
, radio log
, last log
来表明不同的日志输出,这里排查app溃散问题能够只关心system log
和 event log
。
ANR 日志
这里介绍查找ANR仓库信息,可能存在多组仓库轨迹(VM TRACES JUST NOW 和 VM TRACES AT LAST ANR),保证你找的 时间戳 和 PID 是正确的。
----- VM TRACES AT LAST ANR (/data/anr/anr_2022-11-28-16-37-21-918: 2022-11-28 16:37:30) ------
----- pid 30241 at 2022-11-28 16:37:23 -----
Cmd line: com.car300.activity
Build fingerprint: 'meizu/meizu_18X_CN/meizu18X:11/RKQ1.210614.002/1645597308:user/release-keys'
ABI: 'arm64'
Build type: optimized
Zygote loaded classes=15784 post zygote classes=8741
Dumping registered class loaders
#0 dalvik.system.PathClassLoader: [], parent #1
#1 java.lang.BootClassLoader: [], no parent
#2 dalvik.system.PathClassLoader: [/system/framework/tcmclient.jar], parent #0
#3 dalvik.system.PathClassLoader: [], parent #0
#4 dalvik.system.PathClassLoader: [/data/app/~~qmm-6TPCS9yh0WzbcZ3gtw==/com.car300.activity-Hd4Q6adG0VNT8xleGoOIdA==/base.apk:/data/app/~~qmm-6TPCS9yh0WzbcZ3gtw==/com.car300.activity-Hd4Q6adG0VNT8xleGoOIdA==/base.apk!classes9.dex:/data/app/~~qmm-6TPCS9yh0WzbcZ3gtw==/com.car300.activity-Hd4Q6adG0VNT8xleGoOIdA==/base.apk!classes5.dex:/data/app/~~qmm-6TPCS9yh0WzbcZ3gtw==/com.car300.activity-Hd4Q6adG0VNT8xleGoOIdA==/base.apk!classes2.dex:/data/app/~~qmm-6TPCS9yh0WzbcZ3gtw==/com.car300.activity-Hd4Q6adG0VNT8xleGoOIdA==/base.apk!classes6.dex:/data/app/~~qmm-6TPCS9yh0WzbcZ3gtw==/com.car300.activity-Hd4Q6adG0VNT8xleGoOIdA==/base.apk!classes3.dex:/data/app/~~qmm-6TPCS9yh0WzbcZ3gtw==/com.car300.activity-Hd4Q6adG0VNT8xleGoOIdA==/base.apk!classes4.dex:/data/app/~~qmm-6TPCS9yh0WzbcZ3gtw==/com.car300.activity-Hd4Q6adG0VNT8xleGoOIdA==/base.apk!classes7.dex], parent #1
#5 dalvik.system.PathClassLoader: [/system/framework/org.apache.http.legacy.jar], parent #1
Done dumping class loaders
Classes initialized: 4451 in 276.368ms
Intern table: 43228 strong; 536 weak
JNI: CheckJNI is on; globals=933 (plus 80 weak)
Libraries: /data/app/~~qmm-6TPCS9yh0WzbcZ3gtw==/com.car300.activity-Hd4Q6adG0VNT8xleGoOIdA==/lib/arm64/libImSDK.so /data/app/~~qmm-6TPCS9yh0WzbcZ3gtw==/com.car300.activity-Hd4Q6adG0VNT8xleGoOIdA==/lib/arm64/libche300_crypt.so /data/app/~~qmm-6TPCS9yh0WzbcZ3gtw==/com.car300.activity-Hd4Q6adG0VNT8xleGoOIdA==/lib/arm64/libcrashsdk.so /data/app/~~qmm-6TPCS9yh0WzbcZ3gtw==/com.car300.activity-Hd4Q6adG0VNT8xleGoOIdA==/lib/arm64/libijmdetect-drisk.so /data/app/~~qmm-6TPCS9yh0WzbcZ3gtw==/com.car300.activity-Hd4Q6adG0VNT8xleGoOIdA==/lib/arm64/liblocSDK8b.so /data/app/~~qmm-6TPCS9yh0WzbcZ3gtw==/com.car300.activity-Hd4Q6adG0VNT8xleGoOIdA==/lib/arm64/libmmkv.so /data/app/~~qmm-6TPCS9yh0WzbcZ3gtw==/com.car300.activity-Hd4Q6adG0VNT8xleGoOIdA==/lib/arm64/libpangleflipped.so /data/app/~~qmm-6TPCS9yh0WzbcZ3gtw==/com.car300.activity-Hd4Q6adG0VNT8xleGoOIdA==/lib/arm64/libumeng-spy.so libandroid.so libaudioeffect_jni.so libcompiler_rt.so libicu_jni.so libjavacore.so libjavacrypto.so libjnigraphics.so libmedia_jni.so libopenjdk.so libqti_performance.so librs_jni.so libsfplugin_ccodec.so libsoundpool.so libstats_jni.so libwebviewchromium_loader.so (23)
Heap: 26% free, 35MB/48MB; 584026 objects
...
suspend all histogram: Sum: 897us 99% C.I. 0.113us-348.319us Avg: 26.382us Max: 396us
DALVIK THREADS (89):
"Signal Catcher" daemon prio=10 tid=5 Runnable
| group="system" sCount=0 dsCount=0 flags=0 obj=0x14e402c8 self=0x71715e6200
| sysTid=14485 nice=-20 cgrp=default sched=0/0 handle=0x6fefae6cc0
| state=R schedstat=( 7087398 35626 13 ) utm=0 stm=0 core=4 HZ=100
| stack=0x6fef9ef000-0x6fef9f1000 stackSize=995KB
| held mutexes= "mutator lock"(shared held)
native: #00 pc 00000000004a07f4 /apex/com.android.art/lib64/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, int, BacktraceMap*, char const*, art::ArtMethod*, void*, bool)+140)
native: #01 pc 00000000005ade9c /apex/com.android.art/lib64/libart.so (art::Thread::DumpStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, bool, BacktraceMap*, bool) const+376)
native: #02 pc 00000000005cafd4 /apex/com.android.art/lib64/libart.so (art::DumpCheckpoint::Run(art::Thread*)+924)
native: #03 pc 00000000005c4f14 /apex/com.android.art/lib64/libart.so (art::ThreadList::RunCheckpoint(art::Closure*, art::Closure*)+528)
native: #04 pc 00000000005c40e0 /apex/com.android.art/lib64/libart.so (art::ThreadList::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, bool)+1920)
native: #05 pc 00000000005c3580 /apex/com.android.art/lib64/libart.so (art::ThreadList::DumpForSigQuit(std::__1::basic_ostream<char, std::__1::char_traits<char> >&)+776)
native: #06 pc 000000000056f4dc /apex/com.android.art/lib64/libart.so (art::Runtime::DumpForSigQuit(std::__1::basic_ostream<char, std::__1::char_traits<char> >&)+196)
native: #07 pc 0000000000584ad4 /apex/com.android.art/lib64/libart.so (art::SignalCatcher::HandleSigQuit()+1396)
native: #08 pc 0000000000583aa0 /apex/com.android.art/lib64/libart.so (art::SignalCatcher::Run(void*)+348)
native: #09 pc 00000000000b009c /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+64)
native: #10 pc 00000000000503c8 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64)
(no managed stack frames)
...
经过文本阅读始终是低效的,下面就介绍两个GUI东西
ChkBugReport
这是索尼运用 java 开发的一款专门解析 bugreport
陈述的指令行东西。它是一个gradle项目,咱们需求编译才能够得到指令行东西,后边会供给编译好的下载链接
git clone https://github.com/sonyxperiadev/ChkBugReport.git
cd ChkBugReport/core
./gradlew assemble
cd build/distributions
unzip ChkBugReport.zip
cd ChkBugReport
这里不对它的编译做过多介绍,编译产品如下: 挑选对应的渠道的指令行,window 运用 .bat 文件
ChkBugReport bugreport-meizu_18X_CN-RKQ1.210614.002-2022-12-07-11-11-54.zip
这样能够直接解析日志陈述文件,并生成 html 陈述到 bugreport-meizu_18X_CN-RKQ1.210614.002-2022-12-07-11-11-54_out
文件夹
翻开 index.html,就能够快速检查 各种log、ANR、过错 等等信息
Battery Historian
Battery Historian 是一个检查电池相关的信息和事情的东西,支撑Android 5.0 (API 21)和更高版本的Android设备。
它是一个go开发的web服务方式的东西,需求运转在 docker 内
因为无法拜访 gcr.io 的docker镜像,这里运用别人 dockerhub 编译好的镜像 runcare/battery-historian
docker run -it -d -p 9999:9999 runcare/battery-historian --port 9999
拜访 http://localhost:9999
就能够翻开页面,能够上传上面生成的陈述zip文件进行剖析。
这个东西主要是用于剖析电池功耗相关的数据,对体系反常等信息没有显示。
除了运用docker快速运转以外,也能够在本地编译,不过这里不过多介绍了,能够参阅github文档。
结束
看到这里,体系陈述的搜集和检查基本上就这些了,不过 bugreport 对日志的记载有实效和大小限制,只能导出近期的陈述,如果app呈现问题需求排查,尽早的导出日志,避免要害信息被掩盖丢掉。
如果感兴趣的能够了解一下adb bugreport 的源码实现,这些文件怎样生成的,这里不过多介绍。
相关链接
ChkBugReport.zip下载
adb burgrport 源码篇
doc 阅读 bug 陈述
Github ChkBugReport Github Battery Historian
Android adb 下载