Hilog规范化封装:分级日志、线上裁剪、防止敏感信息泄露
Hilog规范化封装:分级日志、线上裁剪、防止敏感信息泄露
日志是开发调试和线上排查问题的核心工具。但很多项目里的日志写得很随意:到处console.info,没有分级,线上Debug日志没关掉,甚至把手机号、身份证号、Token直接打出来。调试的时候方便了,上线之后问题一堆:日志太多影响性能、敏感信息泄露被审核打回、出了问题找不到关键日志。
本文基于最新鸿蒙API,把Hilog的规范化封装讲清楚:分级怎么设、线上怎么裁剪、敏感信息怎么过滤,代码可以直接复制到项目里用。
01 Hilog基础用法与分级
鸿蒙的日志系统叫Hilog,由@kit.PerformanceAnalysisKit提供。基础用法很简单,直接调用info、debug、error这些方法就行。
import { hilog } from '@kit.PerformanceAnalysisKit';
const DOMAIN = 0x0001; // 业务域ID,自定义
const TAG = 'MyApp';
hilog.info(DOMAIN, TAG, '这是一条普通日志');
hilog.debug(DOMAIN, TAG, '这是调试日志');
hilog.error(DOMAIN, TAG, '出错了');
hilog.warn(DOMAIN, TAG, '警告信息');
Hilog有五个日志级别,从低到高:
-
DEBUG:调试级,最详细,开发时用,上线必须关
-
INFO:信息级,关键流程节点,比如页面打开、接口成功
-
WARN:警告级,不影响运行但有隐患,比如接口重试、缓存过期
-
ERROR:错误级,功能出错了,比如接口失败、数据解析异常
-
FATAL:致命级,应用崩溃了,一般系统级用
日志级别的核心作用是过滤。你可以设置一个最低级别,低于这个级别的日志就不输出。比如线上设置成INFO,那DEBUG日志就全部丢弃,不会输出到控制台,也不会占性能。
02 分级日志封装
直接用原生Hilog有几个问题:每个地方都要传domain和tag,写起来麻烦;想统一改日志格式,要改所有地方;没法控制线上哪些级别输出。所以封装一层很有必要。
import { hilog } from '@kit.PerformanceAnalysisKit';
class Logger {
private domain: number = 0x0001;
private tag: string = 'MyApp';
// 配置全局tag
setTag(tag: string) {
this.tag = tag;
}
debug(message: string) {
hilog.debug(this.domain, this.tag, message);
}
info(message: string) {
hilog.info(this.domain, this.tag, message);
}
warn(message: string) {
hilog.warn(this.domain, this.tag, message);
}
error(message: string) {
hilog.error(this.domain, this.tag, message);
}
}
// 全局单例
export const logger = new Logger();
用的时候直接调:
import { logger } from './Logger';
logger.info('首页加载完成');
logger.debug('接口返回数据', JSON.stringify(data));
logger.error('请求失败', error.message);
这样比直接写hilog.info要简洁,而且全局统一了domain和tag。以后想改domain或者加统一前缀,只改Logger类就行,不用动所有调用的地方。
更进一步,可以给每个模块单独设tag。比如用户模块的日志前缀是User,订单模块是Order,排查问题的时候按tag过滤就很方便。
03 线上日志裁剪
开发环境里DEBUG日志越多越好,但上线之后必须关掉。不然用户手机上跑着DEBUG级别日志,性能受影响,日志文件占空间,还可能泄露信息。
裁剪的核心是:根据BuildType判断当前是Debug还是Release版本,决定哪些日志输出。
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BuildTime } from 'build_time';
class Logger {
private domain: number = 0x0001;
private tag: string = 'MyApp';
private isDebug: boolean = BuildTime.DEBUG; // 自动注入是否Debug版本
debug(message: string) {
// 只有Debug版本才输出debug日志
if (this.isDebug) {
hilog.debug(this.domain, this.tag, message);
}
}
info(message: string) {
hilog.info(this.domain, this.tag, message);
}
warn(message: string) {
hilog.warn(this.domain, this.tag, message);
}
error(message: string) {
hilog.error(this.domain, this.tag, message);
}
}
export const logger = new Logger();
BuildTime.DEBUG是编译时自动注入的,Debug打包是true,Release打包是false。这样打包上线之后,所有debug方法直接不执行,连字符串拼接的开销都省了。
除了DEBUG,INFO也可以裁剪。比如上线后只保留WARN和ERROR,普通信息日志全部关掉,性能更好。但一般建议保留INFO,线上出问题排查的时候,关键流程的日志很有用。
还有一个细节:日志里不要拼大对象。比如直接把整个接口返回结果JSON.stringify打出来,数据量大的时候很耗性能。线上版本这些详细日志应该只在DEBUG下输出。
04 敏感信息过滤
这是最容易出事的地方。手机号、身份证号、银行卡号、密码、Token,这些绝对不能打到日志里。一不小心就被应用市场审核打回,甚至触发安全合规问题。
封装日志的时候,统一加一层敏感信息过滤,自动把常见的敏感字段替换成***。
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BuildTime } from 'build_time';
class Logger {
private domain: number = 0x0001;
private tag: string = 'MyApp';
private isDebug: boolean = BuildTime.DEBUG;
// 敏感字段正则
private sensitivePatterns: RegExp[] = [
/1[3-9]\d{9}/g, // 手机号
/\d{17}[\dXx]/g, // 身份证号
/\d{16,19}/g, // 银行卡号
/(?<=token=)\w+/gi, // Token参数
/(?<=password=)\w+/gi // 密码参数
];
// 过滤敏感信息
private filterSensitive(message: string): string {
let result = message;
this.sensitivePatterns.forEach(pattern => {
result = result.replace(pattern, '***');
});
return result;
}
// 统一输出入口
private output(level: string, message: string) {
// 线上版本过滤敏感信息
const filtered = this.isDebug ? message : this.filterSensitive(message);
switch (level) {
case 'debug':
if (this.isDebug) hilog.debug(this.domain, this.tag, filtered);
break;
case 'info':
hilog.info(this.domain, this.tag, filtered);
break;
case 'warn':
hilog.warn(this.domain, this.tag, filtered);
break;
case 'error':
hilog.error(this.domain, this.tag, filtered);
break;
}
}
debug(message: string) {
this.output('debug', message);
}
info(message: string) {
this.output('info', message);
}
warn(message: string) {
this.output('warn', message);
}
error(message: string) {
this.output('error', message);
}
}
export const logger = new Logger();
这样不管谁打日志,线上版本都会自动过滤掉手机号、身份证号这些敏感信息。不用靠开发人员自觉,从底层就兜住了。
正则可以根据自己项目的业务扩展,比如订单号、用户ID这些需要脱敏的,都加进去。Debug版本不过滤,方便开发调试;Release版本自动脱敏,安全合规。
05 完整日志工具类
把分级、裁剪、敏感信息过滤都整合到一起,就是一个可以直接用的日志工具类。
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BuildTime } from 'build_time';
class LogManager {
private domain: number = 0xA001;
private defaultTag: string = 'HarmonyApp';
private isDebug: boolean = BuildTime.DEBUG;
private patterns: RegExp[] = [
/1[3-9]\d{9}/g,
/\d{17}[\dXx]/g,
/[A-Za-z0-9]{20,}/g // 长字符串模拟Token
];
private mask(text: string): string {
let result = text;
this.patterns.forEach(p => result = result.replace(p, '***'));
return result;
}
private log(level: 'D'|'I'|'W'|'E', tag: string, msg: string) {
const content = this.isDebug ? msg : this.mask(msg);
const fullTag = `${this.defaultTag}_${tag}`;
switch(level) {
case 'D':
if (this.isDebug) hilog.debug(this.domain, fullTag, content);
break;
case 'I':
hilog.info(this.domain, fullTag, content);
break;
case 'W':
hilog.warn(this.domain, fullTag, content);
break;
case 'E':
hilog.error(this.domain, fullTag, content);
break;
}
}
d(tag: string, msg: string) { this.log('D', tag, msg); }
i(tag: string, msg: string) { this.log('I', tag, msg); }
w(tag: string, msg: string) { this.log('W', tag, msg); }
e(tag: string, msg: string) { this.log('E', tag, msg); }
}
export const Log = new LogManager();
// 使用示例:
// Log.d('Order', '订单列表请求开始');
// Log.i('User', '用户登录成功,userId: 123');
// Log.e('Pay', '支付失败: 余额不足');
调用的时候传两个参数:模块tag和日志内容。每个模块的日志带自己的前缀,排查问题的时候按tag过滤,一眼就能定位是哪个模块出的问题。
落地注意事项
**不要在循环里打日志。**列表数据循环的时候,不要每条数据都打一条日志。循环一千次就打一千条,性能直接掉下来。要打就打总数和关键统计信息。
**异常日志要带上下文。**error日志不能只写"出错了",要写清楚什么操作、什么参数、什么错误。比如"提交订单失败,orderId=xxx, reason=库存不足",这样线上看到日志就知道是哪里的问题。
**日志TAG要统一规范。**不要一个地方写OrderList,另一个地方写order_list,tag命名不统一,过滤的时候很麻烦。按模块名统一,比如User、Order、Pay、Net,一眼就懂。
**线上日志不要打大对象。**整个接口返回结果、整个数据库查询结果,这些大对象不要直接打到INFO级别。线上版本这些详细日志应该只在DEBUG下输出,不然日志文件会非常大。
小结
日志封装的核心就三件事:分级输出、按构建类型裁剪、敏感信息过滤。封装一层Logger,全局统一调用,不用每个地方都写原生Hilog。开发环境详细日志随便打,上线之后自动裁剪、自动脱敏,性能和安全都有保障。
实际项目里,把日志规范写进团队的代码评审标准里,不能随便console.info,必须走封装好的Logger。时间久了,日志质量上去了,线上排查问题的效率会高很多。
更多推荐



所有评论(0)