为什么日志里总是显示 <private>?把 %{public} 和 %{private} 一次讲清【鸿蒙心迹】

你是不是也在想——“鸿蒙这么火,我能不能学会?”
答案是:当然可以!
这个专栏专为零基础小白设计,不需要编程基础,也不需要懂原理、背术语。我们会用最通俗易懂的语言、最贴近生活的案例,手把手带你从安装开发工具开始,一步步学会开发自己的鸿蒙应用。
不管你是学生、上班族、打算转行,还是单纯对技术感兴趣,只要你愿意花一点时间,就能在这里搞懂鸿蒙开发,并做出属于自己的App!
📌 关注本专栏《零基础学鸿蒙开发》,一起变强!
每一节内容我都会持续更新,配图+代码+解释全都有,欢迎点个关注,不走丢,我是小白酷爱学习,我们一起上路 🚀
全文目录:
前言
开发 HarmonyOS 应用时,很多人第一次接触 HiLog 都会遇到同一个疑惑:明明在代码里打了日志,DevEco Studio 的日志面板里却显示 <private>,完全看不到实际的值。
这不是 bug,是 HiLog 的隐私保护机制在工作。弄清楚 %{public} 和 %{private} 的区别,是写出"能用的日志"的第一步。
一、这个机制解决什么问题
应用日志在开发阶段是调试工具,但日志本身也会被系统记录,甚至在某些情况下被导出用于问题定位。如果日志里直接出现用户名、手机号、订单号、Token、URL,一旦泄露就是隐私问题。
HiLog 的解决思路是:让开发者在写日志时主动声明每个参数的隐私级别。如果你声明这个值是 public,系统就输出明文;如果声明是 private,或者干脆不声明,系统就把这个值替换成 <private>,不管实际内容是什么。
这不是调试模式和发布模式的区别,也不是 Log Level 的问题。只要你不显式标注 %{public},这个参数就永远不会在日志里以明文出现。
二、把规则弄清楚
格式字符串的写法
HiLog 的格式字符串遵循这个结构:
%{隐私标识}参数类型
比如:
%{public}s—— 字符串,公开输出%{private}s—— 字符串,输出<private>%s—— 字符串,未标识,等同于%{private}s,输出<private>%{public}d—— 整数,公开输出%{private}d—— 整数,输出<private>
官方文档明确说明:如果不填写隐私标识,则默认为 private,不输出明文日志。
支持的参数类型:
| 类型符 | 说明 |
|---|---|
s | 字符串 |
d / i | 整数 |
f | 浮点数 |
o / O | 对象(按 JSON 格式输出) |
模块和 API 信息
- 所属 Kit:
PerformanceAnalysisKit - 导入方式:
import { hilog } from '@kit.PerformanceAnalysisKit'; - 系统能力:
SystemCapability.HiviewDFX.HiLog - 起始支持版本:API 9(对应 HarmonyOS 3.1 / 3.0 及以上)
- 仅支持 Stage 模型
hilog 提供五个级别的打印方法,签名相同:
hilog.debug(domain: number, tag: string, format: string, ...args: unknown[]): void
hilog.info(domain: number, tag: string, format: string, ...args: unknown[]): void
hilog.warn(domain: number, tag: string, format: string, ...args: unknown[]): void
hilog.error(domain: number, tag: string, format: string, ...args: unknown[]): void
hilog.fatal(domain: number, tag: string, format: string, ...args: unknown[]): void
domain 的范围是 0x0000~0xFFFF,用来标识日志所属的子系统,可以自行按业务划分。
tag 最多 31 字节,超出部分会被截断,不支持中文字符。
三、搭一个最小验证场景
用四类典型数据做对比:
- 用户名(一般可以公开用于调试)
- 订单号(敏感,应该保护)
- 错误码(业务码,通常可以公开)
- URL(可能含有 token 参数,需要谨慎)
目标:通过同一段代码,观察不同隐私标识在日志面板中的实际输出差异。
四、核心代码实现
先建好基础结构,确认 hilog 正确导入。
import { hilog } from '@kit.PerformanceAnalysisKit';
下面是一个最小示例,在一个按钮点击后触发日志打印,涵盖四种典型数据:
import { hilog } from '@kit.PerformanceAnalysisKit';
const DOMAIN = 0x0001;
const TAG = 'LogDemo';
@Entry
@Component
struct LogDemoPage {
build() {
Column({ space: 20 }) {
Button('触发日志演示')
.onClick(() => {
this.printDemoLogs();
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
printDemoLogs(): void {
const username: string = 'Alice';
const orderId: string = 'ORD-20250601-99281';
const errorCode: number = 4042;
const requestUrl: string = 'https://api.example.com/orders?token=abc123';
// 用户名:公开,调试时需要看到具体值
hilog.info(DOMAIN, TAG, 'username: %{public}s', username);
// 订单号:私有,输出 <private>
hilog.info(DOMAIN, TAG, 'orderId: %{private}s', orderId);
// 错误码:公开,排查问题需要明文
hilog.error(DOMAIN, TAG, 'errorCode: %{public}d', errorCode);
// URL(含 token 参数):私有保护
hilog.info(DOMAIN, TAG, 'requestUrl: %{private}s', requestUrl);
// 演示未标识时的默认行为(等同于 private)
hilog.info(DOMAIN, TAG, 'no-tag orderId: %s', orderId);
}
}
点击按钮后,日志面板中预期看到的输出:
I username: Alice
I orderId: <private>
E errorCode: 4042
I requestUrl: <private>
I no-tag orderId: <private>
五、几个关键点拆开看
1. 未标识不等于"运行时可见"
很多人以为不写 {public} 或 {private} 的话,日志默认是可见的——这个理解是反的。
官方规定是:未标注隐私级别,一律视为 private。写 %s 和写 %{private}s 在日志输出上完全一致,都会看到 <private>。
这也是为什么很多人第一次使用 HiLog 时,觉得"日志打了没反应"。
2. %{public} 不受 Log Level 影响
有开发者会猜:是不是 DEBUG 模式下 private 才显示明文?
不是。HiLog 的隐私标识是独立于日志级别的机制,%{private} 在 debug、info、error 等任意级别下都只会显示 <private>,与是否是调试包无关。
3. 混用标识时,每个参数独立处理
一条日志里可以同时包含 public 和 private 参数,系统分别处理每个占位符:
hilog.info(DOMAIN, TAG, 'user: %{public}s, token: %{private}s', username, token);
// 输出:user: Alice, token: <private>
每个参数只关心自己的标识,互不影响。
4. domain 和 tag 的实际作用
domain 是数值型的日志域标识,在 DevEco Studio 日志面板中用于过滤,实际开发里可以按模块划分,比如 0x0001 对应订单模块,0x0002 对应账户模块。
tag 是字符串标签,方便在日志面板直接搜索定位。注意它不支持中文,且超过 31 字节会被截断,命名时注意控制长度。
5. 对象类型用 %o / %O
如果要把一个对象整体打出来,用 %{public}o 或 %{public}O,系统会按 JSON 格式输出对象内容。同样,不标 public 的话整个对象都是 <private>。
六、容易踩坑的地方
坑 1:用 console.log 替代 HiLog
HarmonyOS 应用开发中 console.log 也能输出日志,但它没有隐私保护机制,也没有 domain/tag 管理,在生产阶段可能造成敏感信息泄露。官方推荐使用 hilog,不建议在应用代码里依赖 console.log 做正式日志。
坑 2:把 URL 整体标为 public
URL 参数里经常携带 token、session_id 等敏感字段。如果图方便把整个 URL 字符串标成 %{public}s,实际上把这些参数也一并暴露在日志里了。更稳妥的方式是只打出 URL 的路径部分,把包含参数的完整 URL 标成 private,或者在打印前手动把敏感参数过滤掉。
坑 3:tag 写了中文
tag 参数不支持中文,如果写了中文标签,实际输出时 tag 字段会出现乱码或截断,导致在日志面板里按 tag 过滤失效。建议始终用英文或拼音缩写。
坑 4:format 和 args 数量不匹配
format 里有几个占位符,args 里就要传几个对应的值。数量不一致不会在编译期报错,但运行时日志输出可能出现参数错位或显示异常。
七、实际排查思路
如果遇到日志中出现 <private>,排查顺序建议这样走:
- 确认是否忘记写隐私标识 —— 检查
format字符串,看是否写了%s、%d这类没有{public}的占位符。 - 确认是否显式写了
{private}—— 如果业务上这个值本来就不应该明文输出,那<private>是正常行为。 - 确认 domain 和 tag 是否在日志面板过滤条件内 —— 有时候不是
<private>的问题,而是这条日志压根没被筛选出来。 - 确认
hilog.isLoggable是否拦截了这条日志 —— 如果在代码里用了isLoggable做前置判断,注意 domain/tag/level 三个参数必须完全匹配才能返回true。 - 确认 import 路径是否正确 —— 应该是
import { hilog } from '@kit.PerformanceAnalysisKit',不是其他路径。
开发经验总结
- HiLog 不标隐私级别的参数,默认就是
private,这个设计是主动保护,不是 bug。 %{public}和%{private}是写在format字符串里的,不是函数参数,初次接触容易找错位置。- 敏感数据的判断没有统一标准,核心原则是:如果这个值出现在日志文件里被他人看到会造成问题,就用
private。 tag只支持英文,写中文是无效的,DevEco Studio 里会搜不到。- 真正养成习惯之后,
%{public}和%{private}加起来不过几个字符,但对于日志合规来说是必要的成本。
如果你的项目里目前用的还是裸 %s 或者 console.log,可以搜一下代码里有多少地方直接打印了带敏感字段的字符串,逐步替换成明确标注隐私级别的 hilog 调用,这比事后出了问题再修代价小很多。
❤️ 如果本文帮到了你…
- 请点个赞,让我知道你还在坚持阅读技术长文!
- 请收藏本文,因为你以后一定还会用上!
- 如果你在学习过程中遇到bug,请留言,我帮你踩坑!
更多推荐




所有评论(0)