2. HiLog API详解:五个核心方法的使用
日志这东西,说简单也简单,说复杂也复杂。我在鸿蒙项目里摸爬滚打这几年,最深的体会就是——日志打得好,调试没烦恼;日志打得烂,加班到天亮。
今天咱们就聊聊HiLog的五个核心方法:debug()、info()、warn()、error()、fatal()。说白了,它们就是你在代码里埋下的「监听器」,帮你随时掌握程序的运行状态。
2.1 方法总览与级别说明
先看一张总览图,让你对五个方法有个整体印象:
嗯,这张图很直观。从下往上看,级别越来越高,严重程度也越来越大。我个人习惯把 debug 当成「日常唠叨」,fatal 当成「红色警报」。
2.2 方法签名与参数说明
每个方法都有统一的签名格式,记住一个就等于记住了五个:
HiLog.debug(label: string, format: string, ...args: any[]): void
HiLog.info(label: string, format: string, ...args: any[]): void
HiLog.warn(label: string, format: string, ...args: any[]): void
HiLog.error(label: string, format: string, ...args: any[]): void
HiLog.fatal(label: string, format: string, ...args: any[]): void
参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| label | string | 日志标签,建议用模块名或类名,如 "LoginModule" |
| format | string | 格式化字符串,支持 %d、%s、%f 等占位符 |
| ...args | any[] | 可变参数,与 format 中的占位符一一对应 |
2.3 各方法实战用法
2.3.1 HiLog.debug() — 开发调试的「放大镜」
debug() 是我用得最多的方法。说白了,它就是你在代码里埋下的「摄像头」,记录各种中间状态和变量值。
// 记录用户登录流程的中间状态
let userName = "testUser";
let loginStep = 3;
let token = "abc123xyz";
HiLog.debug("LoginFlow", "当前用户: %s, 步骤: %d, token: %s",
userName, loginStep, token);
// 输出: [DEBUG] LoginFlow: 当前用户: testUser, 步骤: 3, token: abc123xyz
我在项目中遇到过一个问题:某个功能在真机上正常,在模拟器上就崩。后来加了一堆 debug() 日志,才发现是模拟器的存储路径不一样。你看,多打几行日志,省了多少排查时间。
2.3.2 HiLog.info() — 流程节点的「里程碑」
info() 用来记录关键的业务流程节点。比如「启动完成」、「数据加载成功」、「页面渲染完毕」这类信息。
// 记录应用启动的关键节点
HiLog.info("AppLifecycle", "应用启动完成,耗时: %d ms", startupTime);
HiLog.info("DataLoad", "用户数据加载成功,共 %d 条记录", recordCount);
HiLog.info("PageRender", "首页渲染完成,FPS: %d", currentFps);
你想想看,如果线上用户反馈「打开应用很慢」,你翻翻 info() 日志,看看每个节点的耗时,问题出在哪一步就一目了然了。
2.3.3 HiLog.warn() — 潜在风险的「预警灯」
warn() 用来记录那些「暂时没问题,但值得关注」的情况。比如网络超时重试、缓存命中失败、配置项缺失使用默认值等。
// 网络请求超时,触发重试机制
let retryCount = 2;
HiLog.warn("Network", "请求超时,正在进行第 %d 次重试", retryCount);
// 缓存未命中,回退到默认配置
HiLog.warn("Cache", "缓存未命中,使用默认配置项: %s", configKey);
我曾经在项目里发现一个诡异的问题:某个功能偶尔闪退,但 error() 日志里啥也没有。后来加了 warn() 日志,才发现是某个第三方 SDK 在特定条件下返回了空指针,但被上层 try-catch 吃掉了。嗯,从那以后我养成了习惯——所有 catch 块里至少打一条 warn()。
2.3.4 HiLog.error() — 功能异常的「红色警报」
error() 是线上问题排查的主力军。只要出现 error() 日志,就意味着某个功能已经无法正常工作了。
// 数据库查询失败
try {
let result = db.query(sql);
} catch (e) {
HiLog.error("DB", "查询失败,SQL: %s, 错误: %s", sql, e.message);
}
// 网络请求返回错误码
if (response.code !== 200) {
HiLog.error("API", "请求失败,URL: %s, 状态码: %d", url, response.code);
}
error() 日志都应该附带足够的上下文信息。光写一句「出错了」等于没写。至少要包含:出错位置、错误原因、关键参数。
2.3.5 HiLog.fatal() — 致命崩溃的「最后遗言」
fatal() 是最高级别的日志。它记录的是那些「程序已经无法继续运行」的致命错误。说实话,这个我在实际项目里用得很少,但一旦用上,就是生死攸关的时刻。
// 内存分配失败,应用即将崩溃
HiLog.fatal("Memory", "内存分配失败,当前可用内存: %d MB, 请求大小: %d MB",
availableMem, requestSize);
// 关键资源加载失败,无法继续运行
HiLog.fatal("Resource", "核心资源加载失败: %s,应用即将退出", resourceName);
我记得有一次线上事故,某个低端机型频繁闪退。翻看 fatal() 日志才发现是图片加载时 OOM 了。后来加了内存压缩和分片加载,问题才解决。你看,fatal() 日志虽然不常用,但关键时刻能救命。
2.4 方法选择速查表
| 场景 | 推荐方法 | 示例 |
|---|---|---|
| 开发调试、变量追踪 | debug() | 记录循环中的中间变量 |
| 业务流程节点 | info() | 「数据加载完成」、「页面渲染完毕」 |
| 潜在风险、异常捕获 | warn() | 「重试第2次」、「使用默认配置」 |
| 功能异常、业务失败 | error() | 「数据库查询失败」、「网络请求超时」 |
| 致命错误、应用崩溃 | fatal() | 「内存分配失败」、「核心资源缺失」 |
2.5 避坑指南
最后分享几个我踩过的坑:
- 我曾经在循环里打
debug()日志,结果循环 10000 次,日志刷了 10000 条,直接把 logcat 卡死了。记住:高频场景下慎用日志,或者加个采样率。 - 我曾经把敏感信息(比如密码、token)打到了日志里,结果被安全审计抓了个正着。从那以后,所有涉及隐私的数据我都会先脱敏再打印。
- 我建议每个团队都制定一份日志规范:什么场景用什么级别、label 怎么命名、format 怎么写。别让每个人按自己的喜好来,否则日志系统会变成一团乱麻。
好了,五个方法就讲到这里。记住一个核心原则:日志不是写得越多越好,而是写得越精准越好。下一节咱们聊聊 HiLog 的进阶用法——如何自定义日志格式和过滤规则。
公众号:蓝海资料掘金营,微信deep3321