【DFX系列】Flutter 鸿蒙日志与Trace抓取使用指南
通过上一篇我们打了个基础,今天的这一篇会作为日志专项,重点带你详细解说日志在DFX中的重要作用,并一步步教你怎么用!
一、日志从哪来
Flutter 鸿蒙中的日志来自三个源头:
| 来源 | Tag | 典型内容 |
|---|---|---|
| 引擎内部(FML_LOG) | 映射到 HiLog | 崩溃堆栈、卡死检测、GPU 回收 |
| 平台 C++ 层 | XComFlutterOHOS_Native | 引擎初始化、NAPI 调用 |
| ETS 嵌入层 | Flutter | MethodChannel、插件异常、生命周期 |
如果你不确定要看哪个源头,用一条命令查看全部:
hdc shell hilog | grep -E "Flutter|XComFlutter|flutter"
其中命令里的三个关键字的大小写不同,分别对应 ETS 层、平台 C++ 层和引擎内部的命名习惯,拼在一起才不缺失信息。
二、怎么抓日志
2.1 基本流程:分为四步
不管什么问题,先按四步把日志抓下来:
# 1. 清空历史日志,只留复现后的新日志
hdc shell hilog -r
# 2. 复现问题(操作应用,触发 bug)
# 3. 抓取日志,Ctrl+C 停止
hdc shell hilog > flutter_log.txt
# 4. 筛选 Flutter 相关内容
hdc shell hilog | grep -E "Flutter|XComFlutter|flutter" > flutter_filtered.txt
hilog 是鸿蒙的日志系统,类似 Android 的 logcat。
grep 是文本搜索工具,-E 表示按正则表达式匹配;> 表示把输出保存到文件。
先清空再复现,日志里只有本次问题的记录,搜索范围小得多。
2.2 实时监控:边操作边看
不带输出重定向,命令就变成实时流,按问题方向选一条挂着,同时操作应用:
# 实时看全部 Flutter 日志
hdc shell hilog | grep -E "Flutter|XComFlutter|flutter"
# 实时看崩溃日志
hdc shell hilog | grep -E "Caught signal|Unhandled exception|FLUTTER_"
# 实时看卡死日志
hdc shell hilog | grep -E "FlutterWatchdog|not alive|HiCollie"
# 实时看 GPU 回收日志
hdc shell hilog | grep -E "GpuReclaim|Surface"
# 实时看外接纹理日志
hdc shell hilog | grep -E "external_texture|NativeImage|texture_id"
2.3 抓到设备文件,再拉回到电脑
如果复现时间不好预估时,可以先把日志落在设备上,完事后再拉取:
# 把日志保存到设备文件
hdc shell "hilog > /data/local/tmp/flutter_log.txt"
# 拉取到电脑
hdc file recv /data/local/tmp/flutter_log.txt ./flutter_log.txt
2.4 崩溃专用:tombstone
Native 崩溃时,系统会在 /data/log/faultlog/ 下生成 tombstone 文件,信息比 hilog 详细,这也是必知必会的常识:
# 查看崩溃日志文件
hdc shell ls /data/log/faultlog/
# 拉取到电脑
hdc file recv /data/log/faultlog/faultlog-xxx ./faultlog.txt
2.5 卡死专用:APP_FREEZE
UI 线程卡死 6 秒,系统生成 APP_FREEZE 事件,同样落在 faultlog 目录:
dc shell ls /data/log/faultlog/
hdc file recv /data/log/faultlog/appfreeze-xxx ./appfreeze.txt
三、过滤日志:四个维度
3.1 按问题类型(最常用)
按现象对照选命令,噪音少很多:

3.2 按 Tag 过滤
只关心一个源头时,用 -T 比 grep 快:
# 只看引擎 C++ 日志
hdc shell hilog -T XComFlutterOHOS_Native
# 只看 ArkTS 日志
hdc shell hilog -T Flutter
3.3 按级别过滤
hilog 的级别参数,控制输出门槛:
hdc shell hilog -b D # 全部日志(Debug 及以上)
hdc shell hilog -b I # 只看 Info 及以上
hdc shell hilog -b W # 只看 Warn 及以上
hdc shell hilog -b E # 只看 Error 及以上
五个级别的含义和用途:
| 级别 | 通俗理解 | 什么时候看 |
|---|---|---|
| DEBUG | 最详细的调试信息 | 开发调试时 |
| INFO | 关键流程节点 | 确认流程是否正常 |
| WARN | 警告,可恢复的问题 | 检查潜在问题 |
| ERROR | 错误,功能失败 | 排查问题 |
| FATAL | 致命,不可恢复 | 必须修复 |
排查问题时建议开启 DEBUG 级别:
hdc shell hilog -b D。默认级别会把大量引擎细节拦在门外。
3.4 组合过滤技巧
四个常用组合,覆盖大部分缩小范围的需求:
# 多个关键词,OR 关系
hdc shell hilog | grep -E "GpuReclaim|frame gate|Surface REBUILT"
# 排除噪音,NOT 关系
hdc shell hilog | grep -E "Flutter" | grep -v "flutter::"
# 只看某个时间段:10:30-10:35 的日志
hdc shell hilog | grep "08-03 10:3[0-5]"
# 统计关键词出现次数:卡死了几次
hdc shell hilog | grep -c "is not alive"
grep -v 排除、grep -c 计数,这两个用得最少,卡死类问题统计复现次数时最省事。
四、Release 模式下 ETS 日志看不到怎么办?
Release/Profile 模式默认只输出 WARN 及以上,看不到详细日志。需要在应用入口把级别调回 DEBUG:
import Log from '@ohos.flutter.ohos/src/main/ets/util/Log';
Log.setLogLevel(HiLog.LogLevel.DEBUG);
改完后需要重新打包。
这个开关只影响 ETS 嵌入层的日志,引擎 C++ 层的日志级别由 3.3 节的 -b 参数控制。
五、HiTrace:性能调优专属
HiTrace 是性能追踪工具,记录每一帧的耗时,类似 Chrome DevTools 的 Performance 录制。日志看不出卡顿原因时,就需要切换为 Trace了。
抓 10 秒 Trace,在这 10 秒内复现问题:
hdc shell hitrace --trace_clock boottime -t 10 flutter -o /data/local/tmp/trace.ftrace
hdc file recv /data/local/tmp/trace.ftrace ./trace.ftrace
# 方法1:用 Chrome 打开:访问 chrome://tracing,点 Load,选文件
# 方法2:使用HiSmartPerf
怀疑线程被调度问题拖住时,把调度信息一起抓(时长放到 30 秒):
hdc shell hitrace --trace_clock boottime -t 30 flutter sched -o /data/local/tmp/trace.ftrace
Trace 打开后,按这张表搜索:
| 搜索关键词 | 看什么 | 正常表现 |
|---|---|---|
| flutter::Frame | 每一帧的耗时 | 低于 16ms |
| Flutter Lost Frames | 丢帧计数 | 值为 0 |
| Flutter Hitch Time | 丢帧详情 | 不出现 |
| feedFlutterWatchdog | UI 线程心跳 | 每 3 秒一次 |
| feedFlutterRasterWatchdog | Raster 线程心跳 | 每 3 秒一次 |
两条心跳是卡死排查的锚点:心跳还在,线程活着;心跳断了,去数最后一次心跳之后发生了什么。
这里以HiSmartPerf性能调优工具为例:

Expected Timeline:理想帧泳道图。
Actual Timeline:真实帧泳道图。
可以通过看到子线程的调用关系(举例):

六、关键日志速查(按严重程度)
日志到手后按类别搜关键字。同一行里,严重程度决定了处理的优先级:
崩溃相关
| 关键字 | 含义 | 严重程度 |
|---|---|---|
| Caught signal SIGSEGV | 引擎访问了非法内存 | 致命 |
| Caught signal SIGABRT | 引擎断言失败或堆破坏 | 致命 |
| Unhandled exception | Dart 代码有未捕获异常 | 致命 |
| Failed to handle method call | ETS 插件异常 | 中 |
卡死相关
| 关键字 | 含义 | 严重程度 |
|---|---|---|
| is not alive | 某个线程卡死了 | 致命 |
| m_is_six_second_event = false | 卡死 3 秒,第一阶段 | 严重 |
| m_is_six_second_event = true | 卡死 6 秒,第二阶段,可能弹窗 | 致命 |
| thread may be blocked, do not report | 防误报跳过 | 正常 |
内存 / GPU 相关
| 关键字 | 含义 | 严重程度 |
|---|---|---|
| Dart heap memory usage exceeds threshold | Dart 内存超 1.5GB | 高 |
| GpuReclaim + kAggressive | GPU 资源被回收 | 正常(退后台时) |
| GpuReclaim + kRestore | GPU 资源恢复 | 正常(回前台时) |
| Surface REBUILT | Surface 重建成功 | 正常 |
| SetDisplayWindow failed | Surface 重建失败 | 异常 |
外接纹理相关
| 关键字 | 含义 | 严重程度 |
|---|---|---|
| No DlImage available | 无可绘制画面,黑屏 | 中 |
| frame gate enabled | 后台帧闸门开启 | 正常 |
| skip one frame(slow consumer) | 消费过慢跳帧 | 中 |
| PlatformViewVisibleAreaEventCallback | 可见区域变化 | — |
Vsync 相关
| 关键字 | 含义 | 严重程度 |
|---|---|---|
| vsync_handle_ is nullptr | Vsync 句柄无效 | 致命 |
| AwaitVSync…failed | Vsync 请求失败 | 致命 |
| Failed to dlopen libnative_vsync.so | Vsync 库加载失败 | 致命 |
七、常见问题
Q1:抓不到 Flutter 日志?
| 原因 | 解决方法 |
|---|---|
| 日志级别没开 | hdc shell hilog -b D |
| hilog 服务没运行 | hdc shell hilog -v 查状态,hdc shell hilog -r 清空重试 |
| 设备没连接 | hdc list targets |
Q2:HiAppEvent 事件在哪里看?
三个入口,从轻到重:
# 方法 1:搜索上报日志
hdc shell hilog | grep "OH_HiAppEvent_Write"
# 方法 2:搜索特定事件
hdc shell hilog | grep -E "FLUTTER_DART_EXCEPTION|OTHER_JANK|FLUTTER_STABILITY_EVENT"
# 方法 3:查看 faultlog 目录
hdc shell ls /data/log/faultlog/
Q3:HiAppEvent 事件上报失败?
| 错误日志 | 含义 | 解决方法 |
|---|---|---|
| API version too low | 系统 API 太低 | 需 API 18+ |
| reportFrameworkMemAnomaly_ is nullptr | 内存上报 API 不足 | 需 API 26+ |
| flush isValid_ false | HiAppEvent 没初始化 | 检查 SO 库加载 |
Q4:怎么确认日志属于哪个线程?
| 搜索关键词 | 对应线程 |
|---|---|
| FlutterUiThread / feedFlutterWatchdog | UI 线程 |
| FlutterRasterThread / feedFlutterRasterWatchdog | Raster 线程 |
| FlutterPlatformThread / feedFlutterPlatformWatchdog | Platform 线程 |
下一篇是Crash相关的专项:大家期待下~
小伙伴们记得点赞+关注
CPF-Flutter社区官网:
https://atomgit.com/CPF-Flutter
“AI再牛,技术不能丢”
更多推荐


所有评论(0)