)
在跨平台应用开发中构建一套统一的日志系统是保障应用可观测性与线上问题快速定位的基石。ArkUI-X 提供了从 ArkTS 层到各原生平台层的完整日志拦截与输出方案。一、 跨平台统一日志工具封装在 ArkTS 业务层建议封装一个统一的日志工具类。该类内部通过平台检测机制自动适配不同平台的底层日志接口如鸿蒙的hilog与其他平台的console确保业务代码中日志调用的一致性。核心代码示例统一日志拦截与分发import { PlatformDetector } from ./PlatformDetector; // 假设的平台检测工具 import { hilog } from kit.PerformanceAnalysisKit; class CrossPlatformLogger { private static readonly DOMAIN: number 0x0000; static info(tag: string, message: string) { if (PlatformDetector.isHarmonyOS()) { hilog.info(CrossPlatformLogger.DOMAIN, tag, %{public}s, message); } else { console.info([INFO] [${tag}] ${message}); } } static error(tag: string, message: string) { if (PlatformDetector.isHarmonyOS()) { hilog.error(CrossPlatformLogger.DOMAIN, tag, %{public}s, message); } else { console.error([ERROR] [${tag}] ${message}); } } }二、 Android 侧 LogInterface 注入与拦截在 Android 平台ArkUI-X 框架支持通过注入ILogger接口来拦截框架层及 ArkTS 侧输出的日志。开发者可以在 Android 的Application初始化阶段完成注入将跨平台日志统一接管至 Android 原生的日志系统中。核心代码示例Android 日志接口实现与注入// 1. 实现 ILogger 接口 public class AppLogInterface implements ILogger { Override public boolean isDebuggable() { return true; } Override public void i(String tag, String msg) { Log.i(tag, msg); } Override public void e(String tag, String msg) { Log.e(tag, msg); } // ... 实现其他级别日志方法 } // 2. 在 MyApplication 中注入 public class MyApplication extends StageApplication { Override public void onCreate() { super.onCreate(); StageApplicationDelegate appDelegate new StageApplicationDelegate(); appDelegate.setLogInterface(new AppLogInterface()); // 注入日志接口 appDelegate.setLogLevel(ILogger.LOG_DEBUG); // 设置拦截等级 } }三、 命令行日志查看ACE Tools在开发与调试阶段开发者无需依赖各平台的复杂原生工具可直接使用 ArkUI-X 提供的ace log命令行工具。该工具支持一键滚动展示当前连接设备Android、iOS 或 HarmonyOS上正在运行的跨平台应用进程日志极大提升了多端调试的效率。四、 线上日志安全与持久化策略在生产环境中日志系统需兼顾性能与数据安全动态日志降级默认仅拦截并输出ERROR和FATAL级别日志。若需排查线上疑难杂症可通过远程配置动态下发开关临时将日志级别开放至INFO或DEBUG需注意开放低级别日志可能带来的性能损耗与崩溃风险。敏感信息脱敏在日志输出前必须对用户隐私数据、Token、密码等进行正则匹配与掩码脱敏处理。异步落盘对于需要持久化的关键日志应将其写入操作投递至后台 IO 线程避免频繁的磁盘 I/O 阻塞主 UI 线程。五、 跨平台结构化日志与 JSON 格式化输出在大型分布式架构与统一日志聚合平台如 ELK Stack中纯文本格式的日志难以被自动提取关键字段。ArkTS 侧的日志输出应全面拥抱结构化数据将TraceId、UserId、StatusCode等关键上下文信息封装为 JSON 格式以便后端系统高效检索。核心代码示例JSON 结构化日志封装class StructuredLogger { static info(tag: string, message: string, context?: Recordstring, Object) { const logPayload { level: INFO, tag: tag, msg: message, timestamp: Date.now(), traceId: req-123456, // 从全局上下文中获取 TraceId extra: context || {} }; // 统一输出 JSON 字符串便于后续日志解析 CrossPlatformLogger.info(tag, JSON.stringify(logPayload)); } } // 业务调用示例 StructuredLogger.info(NetworkModule, API Request Failed, { url: /api/v1/user, statusCode: 500 });六、 原生侧 Bridge 日志拦截与统一透传跨平台通信Bridge是问题频发的重灾区。为了确保 ArkTS 与原生侧的通信链路完全可追溯建议在 Android/iOS 原生侧的 Bridge 插件中增加日志拦截器将方法调用的入参、出参及耗时统一输出并复用前文配置的ILogger接口进行透传。核心代码示例Android Bridge 日志拦截// 在原生 Bridge 插件中拦截方法调用 public class SafeBridgePlugin extends BridgePlugin { Override public void onMethodCall(String method, JSONObject params, ResultCallback callback) { long startTime System.currentTimeMillis(); // 统一透传至跨平台日志系统 AppLogInterface.logBridgeCall(method, params); super.onMethodCall(method, params, (result) - { long duration System.currentTimeMillis() - startTime; AppLogInterface.logBridgeResult(method, duration, result); callback.onResult(result); }); } }七、 本地日志异步落盘与文件轮转机制当应用处于离线状态或发生致命崩溃Crash时内存中的日志会随之丢失。必须建立可靠的本地日志持久化机制将关键日志异步写入本地文件并配合文件轮转策略防止磁盘空间被撑爆。核心代码示例基于 TaskPool 的异步落盘import { taskpool } from kit.ArkTS; Concurrent async function writeLogToFile(logLine: string, filePath: string): Promisevoid { // 在后台 IO 线程执行文件追加写入操作绝不阻塞主 UI 线程 // 实际开发中可结合 fileIo 进行追加写入及文件大小检测超 10MB 则重命名归档 console.info([IO Thread] Writing log to ${filePath}); } // 在统一日志工具中触发落盘 CrossPlatformLogger.error(CrashModule, App Freeze Detected); taskpool.execute(writeLogToFile, [ERROR] App Freeze Detected, /data/storage/app_crash.log);八、 线上日志动态采集与隐私脱敏合规在生产环境中日志系统不仅要“能写”还要“安全地写”。对于线上疑难杂症需支持通过远程配置如动态下发开关临时提升日志级别同时必须在日志落盘前对敏感信息进行合规处理。核心代码示例正则脱敏与动态开关class SecureLogger { // 敏感信息脱敏正则隐藏手机号中间四位、Token 等 private static readonly SENSITIVE_REGEX: RegExp /(\d{3})\d{4}(\d{4})/g; static safeLog(tag: string, message: string) { // 1. 检查远程下发的日志开关默认生产环境关闭 DEBUG if (!RemoteConfig.isLogEnabled()) return; // 2. 执行脱敏处理 const safeMessage message.replace(SecureLogger.SENSITIVE_REGEX, $1****$2); // 3. 输出安全日志 CrossPlatformLogger.info(tag, safeMessage); } }