通过上一篇我们打了个基础,今天的这一篇会作为日志专项,重点带你详细解说日志在DFX中的重要作用,并一步步教你怎么用!

一、日志从哪来

Flutter 鸿蒙中的日志来自三个源头:

来源Tag典型内容
引擎内部(FML_LOG)映射到 HiLog崩溃堆栈、卡死检测、GPU 回收
平台 C++ 层XComFlutterOHOS_Native引擎初始化、NAPI 调用
ETS 嵌入层FlutterMethodChannel、插件异常、生命周期

如果你不确定要看哪个源头,用一条命令查看全部:

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丢帧详情不出现
feedFlutterWatchdogUI 线程心跳每 3 秒一次
feedFlutterRasterWatchdogRaster 线程心跳每 3 秒一次

两条心跳是卡死排查的锚点:心跳还在,线程活着;心跳断了,去数最后一次心跳之后发生了什么。

这里以HiSmartPerf性能调优工具为例:
在这里插入图片描述

Expected Timeline:理想帧泳道图。
Actual Timeline:真实帧泳道图。

可以通过看到子线程的调用关系(举例):
在这里插入图片描述

六、关键日志速查(按严重程度)

日志到手后按类别搜关键字。同一行里,严重程度决定了处理的优先级:

崩溃相关

关键字含义严重程度
Caught signal SIGSEGV引擎访问了非法内存致命
Caught signal SIGABRT引擎断言失败或堆破坏致命
Unhandled exceptionDart 代码有未捕获异常致命
Failed to handle method callETS 插件异常

卡死相关

关键字含义严重程度
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 thresholdDart 内存超 1.5GB
GpuReclaim + kAggressiveGPU 资源被回收正常(退后台时)
GpuReclaim + kRestoreGPU 资源恢复正常(回前台时)
Surface REBUILTSurface 重建成功正常
SetDisplayWindow failedSurface 重建失败异常

外接纹理相关

关键字含义严重程度
No DlImage available无可绘制画面,黑屏
frame gate enabled后台帧闸门开启正常
skip one frame(slow consumer)消费过慢跳帧
PlatformViewVisibleAreaEventCallback可见区域变化

Vsync 相关

关键字含义严重程度
vsync_handle_ is nullptrVsync 句柄无效致命
AwaitVSync…failedVsync 请求失败致命
Failed to dlopen libnative_vsync.soVsync 库加载失败致命

七、常见问题

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_ falseHiAppEvent 没初始化检查 SO 库加载

Q4:怎么确认日志属于哪个线程?

搜索关键词对应线程
FlutterUiThread / feedFlutterWatchdogUI 线程
FlutterRasterThread / feedFlutterRasterWatchdogRaster 线程
FlutterPlatformThread / feedFlutterPlatformWatchdogPlatform 线程

下一篇是Crash相关的专项:大家期待下~

小伙伴们记得点赞+关注

CPF-Flutter社区官网:

https://atomgit.com/CPF-Flutter

“AI再牛,技术不能丢”

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐