资讯动态

CANN Runtime ACL 日志接口实战:在应用程序中使用 acl_log.h 记录与回调设备日志

发布时间:2026/9/20 6:18:01 来源:尧图企业网站定制
CANNAscend人工智能任务调度【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址https://gitcode.com/cann/runtime点击查看免费下载本技术指南围绕 CANN/runtime 开源仓库中的0_acl_log样例讲解如何在用户应用中通过对外 ACL 日志接口acl_log.h记录调试日志、运行日志与va_list日志并注册/注销设备日志回调。读完本文你将掌握acllogRecord、acllogVaList、acllogCheckDebugLevel、acllogRegisterCallback、acllogUnregisterCallback五个接口的完整用法、底层实现机制以及如何将样例快速编译运行并集成到自己的 CANN 应用中。一、样例定位与核心能力0_acl_log是 CANN/runtime 仓库example/5_performance/log目录下的一个可运行样例覆盖了对外 ACL 日志接口Public ACL Logging APIs的全部五个核心 API。其设计目标非常明确让用户模块在不侵入 CANN 内部日志框架的前提下把自定义日志安全地写入 CANN 统一的日志体系同时允许应用注册自己的回调函数来接收日志内容。该样例覆盖的接口全部声明于仓库头文件 include/dfx/base/acl_log.h包含三类能力能力类别接口作用日志记录acllogRecord以变参printf风格记录一条日志参数带__attribute__((format(printf, 3, 4)))编译期格式检查日志记录acllogVaList以va_list形式记录日志适用于封装了日志函数的中间层级别检查acllogCheckDebugLevel查询指定模块在指定日志级别下是否开启输出1 开启 / 0 关闭回调注册acllogRegisterCallback注册设备日志回调接收日志类型、内容与长度回调注销acllogUnregisterCallback注销已注册的回调句柄从acl_log.h源码可见acllogRecord、acllogVaList、acllogCheckDebugLevel三个函数被声明为weak 弱符号__attribute((weak))这是刻意的兼容性设计当宿主 CANN 环境未提供这些符号时应用仍可正常链接、运行样例会打印[WARN]提示并继续执行回调验证只有acllogRegisterCallback与acllogUnregisterCallback是强符号保证回调机制一定可用。二、样例编译与运行2.1 运行环境准备样例需要一套可用的 CANN 环境。仓库提供了自动探测环境的公共脚本 example/common/resolve_cann_env.shrun.sh会依次探测以下候选路径按优先级排列环境变量ASCEND_INSTALL_PATH环境变量ASCEND_HOME_PATH${HOME}/Ascend/cann${HOME}/Ascend/ascend-toolkit/latest/usr/local/Ascend/cann/usr/local/Ascend/ascend-toolkit/latest/opt/Ascend/cann探测逻辑同时校验include/acl/acl.h与lib64/libacl_rt.so或按x86_64-linux/aarch64-linux架构目录匹配是否真实存在命中后自动source对应环境的set_env.sh或bin/setenv.bash。因此你既可以手动source环境也可以仅靠环境变量指定安装路径。2.2 编译运行步骤进入样例所在的 log 目录执行目录级脚本source ${install_root}/cann/set_env.sh cd ${git_clone_path}/example/5_performance/log bash run.sh脚本内部做了如下事情见 example/5_performance/log/run.sh设置set -euo pipefail任何一步失败立即终止调用resolve_cann_env探测并加载 CANN 环境执行cmake -B build -DASCEND_CANN_PACKAGE_PATH${ASCEND_INSTALL_PATH}配置构建执行cmake --build build -j$(nproc)并行编译运行生成的可执行文件./build/0_acl_log/acl_log_sample输出通过tee同时落盘到output_msg.txt检查输出中是否包含成功标记[SUCCESS] ACL log sample completed successfully.命中则返回 0否则返回非 0。退出码语义返回 0 表示构建与运行全部成功非 0 表示构建或运行失败详细输出可在output_msg.txt中查看见 example/5_performance/log/README.md。2.3 构建配置解读样例的构建配置非常轻量见 example/5_performance/log/0_acl_log/CMakeLists.txt头文件搜索路径仓库自带的../../../../include/dfx/base即include/dfx/base提供acl_log.h与log_types.h以及 CANN 安装包中的${ASCEND_CANN_PACKAGE_PATH}/include/base链接库${ASCEND_CANN_PACKAGE_PATH}/lib64/libascendalog.so即ascendalog 日志动态库ACL 日志接口最终由该库导出实现。父级 example/5_performance/log/CMakeLists.txt 通过add_subdirectory(0_acl_log)组织子样例并通过ASCEND_CANN_PACKAGE_PATH缓存变量CACHE PATH强制要求调用方显式传入 CANN 安装路径未设置时直接FATAL_ERROR。三、日志记录接口深入3.1 调试日志与运行日志的写入样例主程序在头文件acl_log.h中确认acllogRecord、acllogVaList、acllogCheckDebugLevel三个可选符号均已加载后依次执行三类日志记录见 example/5_performance/log/0_acl_log/main.cppconstexpr int32_t kUserModuleId 0xff00; acllogRecord(kUserModuleId, DLOG_INFO, user debug log: %d\n, 1); acllogRecord(kUserModuleId | RUN_LOG_MASK, DLOG_INFO, user run log: %d\n, 2);这里体现了 ACL 日志接口最核心的双通道设计第一条只传kUserModuleId不带掩码日志默认走debug 调试日志通道第二条在模块 ID 上按位或RUN_LOG_MASK0x01000000U日志进入run 运行日志通道。日志类型掩码定义于 include/dfx/base/log_types.h掩码宏值含义DEBUG_LOG_MASK0x00010000U输出到 debug 日志目录SECURITY_LOG_MASK0x00100000U输出到 security 日志目录RUN_LOG_MASK0x01000000U输出到 run 日志目录STDOUT_LOG_MASK0x10000000U输出到 stdoutkUserModuleId 0xff00是自定义模块 ID避开与内置模块编号冲突。内置模块 ID 从SLOG(0)到ACLRTC(76)INVALID_MODULE_ID(77)之后含才是合法可用的自定义区间见 include/dfx/base/log_types.h 中的模块枚举。日志级别同样定义于log_types.h自上而下为级别宏值含义DLOG_DEBUG0x0调试级别DLOG_INFO0x1信息级别DLOG_WARN0x2告警级别DLOG_ERROR0x3错误级别DLOG_NULL0x4不打印日志acllogRecord的签名见 include/dfx/base/acl_log.hLOG_FUNC_VISIBILITY void acllogRecord(int32_t moduleId, int32_t level, const char* fmt, ...) __attribute((weak)) __attribute__((format(printf, 3, 4)));format(printf, 3, 4)声明让编译器在编译期就校验fmt与可变参数的匹配性规避格式化字符串漏洞。LOG_FUNC_VISIBILITY在非 Windows 平台展开为__attribute__((visibility(default)))保证符号对外可见见 include/dfx/base/log_types.h。3.2 通过 va_list 记录日志当你的代码需要在日志封装函数中转发可变参数时应使用acllogVaList。样例的封装如下void RecordWithVaList(int32_t moduleId, int32_t level, const char* format, ...) { va_list args; va_start(args, format); acllogVaList(moduleId, level, format, args); va_end(args); } // 调用 RecordWithVaList(kUserModuleId, DLOG_WARN, user va_list log: %s\n, ok);acllogVaList的签名与acllogRecord完全对应只是可变参数被替换为va_list同样为 weak 符号。这是日志中间层、跨线程转发日志时的标准做法与 C 标准库的vfprintf/fprintf关系一致。3.3 日志级别开关检查在日志量大的场景中先查开关再拼装日志可避免无谓的格式化开销const int32_t debugLevelEnabled acllogCheckDebugLevel(kUserModuleId, DLOG_INFO); std::printf([INFO] acllogCheckDebugLevel returned %d.\n, debugLevelEnabled);acllogCheckDebugLevel(moduleId, logLevel)返回 1 表示该模块该级别已开启0 表示关闭。它对应底层alog_pub.h中AlogCheckDebugLevel(uint32_t moduleId, int32_t level)的模块级开关查询语义见 include/dfx/base/alog_pub.h建议在使用acllogRecord之前先通过它判断是否需要构造日志内容。四、设备日志回调机制4.1 回调注册与回调函数形态回调机制是本样例的另一半核心。样例注册代码如下acllogCallbackHandle callbackHandle 0; const int32_t registerResult acllogRegisterCallback(LogCallback, nullptr, OUTPUT_TYPE_BOTH, callbackHandle); if (registerResult ! 0) { std::printf([FAILURE] acllogRegisterCallback returned %d.\n, registerResult); return 1; }回调函数签名与接口定义一一对应见 include/dfx/base/acl_log.htypedef int32_t (*acllogRecordCallback)(void* userData, uint32_t outputLogType, const char* logContent, size_t length); int32_t LogCallback(void*, uint32_t outputLogType, const char* logContent, size_t length) { std::printf([CALLBACK type%u] %.*s, outputLogType, static_castint(length), logContent); return 0; }参数含义userData注册时传入的用户数据指针样例传nullptr可用于把上下文传递回回调outputLogType日志输出类型取值为acllogOutputLogType枚举logContent/length日志内容缓冲区指针及其字节长度。注意回调按长度而不是以\0结尾的方式消费内容因此样例使用%.*s的精度限定打印这是正确且安全的使用姿势。4.2 日志输出类型枚举acllogOutputLogType枚举同样定义在acl_log.h枚举值值含义OUTPUT_TYPE_DEBUG0仅接收调试日志OUTPUT_TYPE_RUN1仅接收运行日志OUTPUT_TYPE_BOTH2同时接收调试与运行日志OUTPUT_TYPE_MAX3枚举上界哨兵值不可作为入参回调句柄类型为acllogCallbackHandle即uintptr_t注册成功后由接口回填注销时原样传回即可const int32_t unregisterResult acllogUnregisterCallback(callbackHandle); if (unregisterResult ! 0) { std::printf([FAILURE] acllogUnregisterCallback returned %d.\n, unregisterResult); return 1; }acllogRegisterCallback与acllogUnregisterCallback返回int32_t0 表示成功。从acl_log.h可见这两个接口不是weak 符号说明回调能力在依赖libascendalog.so的环境中是强制提供的这也与样例回调接口必验证、记录接口可选验证的健壮性设计相呼应。4.3 与底层 alog 接口的关系acl_log.h是对 CANN 底层日志框架alog的对外封装alog_pub.hinclude/dfx/base/alog_pub.h中提供了更贴近底层的接口AlogCheckDebugLevel(uint32_t moduleId, int32_t level)查询模块级 debug 日志开关返回 1 开启 / 0 关闭AlogRecord(uint32_t moduleId, uint32_t logType, int32_t level, const char* fmt, ...)记录日志logType取DLOG_TYPE_DEBUG(0)/DLOG_TYPE_RUN(1)见log_types.h中的log type枚举。对照可见acllog系列接口将底层AlogRecord的模块 ID 类型 级别三元参数简化为模块 ID内部按掩码区分 debug/run 级别的二元参数并在模块 ID 上通过RUN_LOG_MASK等掩码位表达日志通道降低了用户侧的使用复杂度。需要手动控制单条日志通道时仍可回退到底层AlogRecord的DLOG_TYPE_*参数。五、日志级别与环境变量联动0_acl_log样例虽然本身不解析环境变量但它写入的 debug/run 日志实际受 CANN 全局日志配置控制理解这一点有助于在实际项目中正确预期样例输出ASCEND_GLOBAL_LOG_LEVEL全局日志级别样例中以DLOG_INFO记录的日志只有在该变量设置的级别 ≤ INFO 时才会真正落盘ASCEND_MODULE_LOG_LEVEL按模块细粒度设置级别格式与模块 ID 相关ASCEND_GLOBAL_EVENT_ENABLE事件级别日志开关ASCEND_LOG_PRINT_TO_STDOUT/ASCEND_SLOG_PRINT_TO_STDOUT控制日志是否同时输出到 stdout与STDOUT_LOG_MASK掩码语义互补。这些环境变量的完整说明可参见仓库文档 docs/zh/env_vars/ASCEND_GLOBAL_LOG_LEVEL.md、docs/zh/env_vars/ASCEND_MODULE_LOG_LEVEL.md、docs/zh/env_vars/ASCEND_LOG_PRINT_TO_STDOUT.md 与 docs/zh/log_ref/setting_log_levels.md。日志框架的整体视图可参考 docs/zh/log_ref/log_overview.md。六、成功标记与结果验证样例运行完成后会在 stdout 输出两条关键标记同时被tee写入output_msg.txt[CALLBACK type2] user debug log: 1 [CALLBACK type2] user run log: 2 [CALLBACK type2] user va_list log: ok [INFO] acllogCheckDebugLevel returned 1. [SUCCESS] ACL log sample completed successfully.逐行解读三行[CALLBACK type2]type2即OUTPUT_TYPE_BOTH证明注册的回调同时收到了 debug 日志、run 日志模块 ID 带RUN_LOG_MASK的通道以及经va_list转发的告警日志acllogCheckDebugLevel returned 1说明当前环境下0xff00模块的 INFO 级别调试开关处于开启状态[SUCCESS]行run.sh通过grep精确匹配该行来判断样例执行成功缺失则返回非 0 退出码。需要说明的是acllogCheckDebugLevel的具体返回值受当前 CANN 环境的全局日志级别设置影响acllogRecord系列为 weak 符号若宿主环境未导出这些符号样例走[WARN] Optional ACL log record APIs are unavailable分支仅验证回调接口程序仍正常结束。这正是样例针对不同 CANN 版本所做的兼容性处理样例源码见 example/5_performance/log/0_acl_log/main.cpp。七、将 ACL 日志集成到自己的应用参考样例在自己的 CANN 应用中接入 ACL 日志只需四步引入头文件将 include/dfx/base/acl_log.h 所在目录加入头文件搜索路径或直接使用 CANN 安装包include/base链接动态库链接${ASCEND_CANN_PACKAGE_PATH}/lib64/libascendalog.so选择自定义模块 ID使用INVALID_MODULE_ID(77)之后的数值或直接使用0xff00这类高位自定义值避开内置模块枚举按需组织日志代码常规路径用acllogRecord(moduleId, level, fmt, ...)封装层用acllogVaList高开销日志前先acllogCheckDebugLevel判开关需要接收设备侧日志则acllogRegisterCallback注册回调并在退出前acllogUnregisterCallback注销。这套接口位于 CANN 对外头文件目录include/dfx/base属于官方对外日志能力适用于调试期排查、运行期留痕以及自定义维测工具对接等场景对于不需要输出到 CANN 日志体系的纯业务日志仍应使用应用自身的日志框架避免日志双写带来的性能开销。赞分享CANNAscend人工智能任务调度【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址https://gitcode.com/cann/runtime点击查看免费下载相关推荐9大网盘直链下载助手告别龟速下载的智能解决方案9大网盘直链下载助手告别龟速下载的智能解决方案 还在为网盘下载速度慢、操作繁琐而烦恼吗LinkSwift网盘直链下载助手为您提供了一站式解决方案。这款基于JCANNAscend人工智能任务调度黑苹果安装终极指南用OpCore Simplify工具30分钟搞定OpenCore配置黑苹果安装终极指南用OpCore Simplify工具30分钟搞定OpenCore配置 还在为复杂的黑苹果配置而烦恼吗面对繁琐的OpenCore设置无从下手CANNAscend人工智能任务调度eSearch日志系统应用日志记录与调试工具eSearch日志系统应用日志记录与调试工具 痛点跨平台应用调试的挑战 你是否曾经遇到过这样的困境在开发或使用跨平台应用时当程序出现异常或性能问题时难桌面应用OCR屏幕录制视频处理图像处理上一篇Home Assistant操作系统重置失败问题分析与解决方案下一篇消息撤回克星RevokeMsgPatcher 2.1 防撤回功能全攻略创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价