已合并
feat: ASCEND_SLOG_PRINT_TO_STDOUT环境变量改名 (#768) #3919
feat: ASCEND_SLOG_PRINT_TO_STDOUT环境变量改名 (#768) #3919
已合并
GuoWenbo创建于 7月29日
共 7 个文件变更+339-39
@@ -173,7 +173,7 @@ echo -e "\n=== 分析完成 ==="
173```bash173```bash
174# 设置日志级别(环境变量方式)174# 设置日志级别(环境变量方式)
175export ASCEND_GLOBAL_LOG_LEVEL=0 # DEBUG级别,输出最详细日志175export ASCEND_GLOBAL_LOG_LEVEL=0 # DEBUG级别,输出最详细日志
176-export ASCEND_SLOG_PRINT_TO_STDOUT=1 # 输出到标准输出176+export ASCEND_LOG_PRINT_TO_STDOUT=1 # 输出到标准输出
177 177 
178# 或在代码中设置178# 或在代码中设置
179aclError error = aclInit(nullptr);179aclError error = aclInit(nullptr);
Rdocs/zh/env_vars/ASCEND_SLOG_PRINT_TO_STDOUT.md→docs/zh/env_vars/ASCEND_LOG_PRINT_TO_STDOUT.md+3-3
@@ -1,4 +1,4 @@
1-# ASCEND\_SLOG\_PRINT\_TO\_STDOUT1+# ASCEND\_LOG\_PRINT\_TO\_STDOUT
2 2 
3## 功能描述3## 功能描述
4 4 
@@ -12,13 +12,13 @@
12 12 
13> [!NOTE]说明13> [!NOTE]说明
14>14>
15->- 通过执行**echo $ASCEND\_SLOG\_PRINT\_TO\_STDOUT**命令可以查看环境变量设置的值。15+>- 通过执行**echo $ASCEND\_LOG\_PRINT\_TO\_STDOUT**命令可以查看环境变量设置的值。
16>- 若环境变量未配置/配置为非法值/配置为空,表示采用日志默认输出方式。16>- 若环境变量未配置/配置为非法值/配置为空,表示采用日志默认输出方式。
17 17 
18## 配置示例18## 配置示例
19 19 
20```sh20```sh
21-export ASCEND_SLOG_PRINT_TO_STDOUT=121+export ASCEND_LOG_PRINT_TO_STDOUT=1
22```22```
23 23 
24## 使用约束24## 使用约束
@@ -0,0 +1,36 @@
1+# ASCEND\_SLOG\_PRINT\_TO\_STDOUT(废弃)
2+ 
3+> [!WARNING]废弃说明
4+>
5+> ASCEND\_SLOG\_PRINT\_TO\_STDOUT环境变量在CANN 9.2.0版本标记废弃,将在13.0.0版本删除,替换为:[**ASCEND\_LOG\_PRINT\_TO\_STDOUT**](ASCEND_LOG_PRINT_TO_STDOUT.md)。
F
Ffujun198月11日

【一般】【Normal】旧变量仍处于兼容期,issue 最新结论也是到 13.0.0 再删除;但本 PR 把原 docs/zh/env_vars/ASCEND_SLOG_PRINT_TO_STDOUT.md 重命名后,head 上旧路径已 404(base 为 200)。这会让既有按环境变量名访问的文档入口提前失效,建议保留原文件名作为废弃页,或补充等价跳转/索引兼容,再新增 ASCEND_LOG_PRINT_TO_STDOUT.md。\n\n代码位置:https://gitcode.com/cann/runtime/blob/b8df2fbf8ec8e24891184990789d4d1592cd0c59/docs/zh/env_vars/ASCEND_SLOG_PRINT_TO_STDOUT_deprecated.md#L5-L5

likedislike
GuoWenbo
8月14日 评论:
6+>
7+> 不建议用户使用,以防止引发兼容性问题。若同时配置两者,以**ASCEND\_LOG\_PRINT\_TO\_STDOUT**为准。
8+ 
9+## 功能描述
10+ 
11+是否开启Host侧应用类日志打印。开启后,日志将不会保存在log文件中,而是将产生的日志直接打印显示。
12+ 
13+取值为:
14+ 
15+- 0:关闭日志打印,即日志采用默认输出方式,将日志保存在log文件中。
16+- 1:开启日志打印。
17+- 其他值为非法值。
18+ 
19+> [!NOTE]说明
20+>
21+>- 通过执行**echo $ASCEND\_SLOG\_PRINT\_TO\_STDOUT**命令可以查看环境变量设置的值。
22+>- 若环境变量未配置/配置为非法值/配置为空,表示采用日志默认输出方式。
23+ 
24+## 配置示例
25+ 
26+```sh
27+export ASCEND_SLOG_PRINT_TO_STDOUT=1
28+```
29+ 
30+## 使用约束
31+ 
32+无
33+ 
34+## 支持的型号
35+ 
36+全量芯片支持
@@ -193,7 +193,7 @@ sudo timedatectl set-timezone Asia/Shanghai
193 193 
194**异常现象**194**异常现象**
195 195 
196-用户未设置日志打印环境变量(`export ASCEND_SLOG_PRINT_TO_STDOUT=1`),但是在屏幕上仍有日志显示。196+用户未设置日志打印环境变量(`export ASCEND_LOG_PRINT_TO_STDOUT=1`),但是在屏幕上仍有日志显示。
197 197 
198**可能原因**198**可能原因**
199 199 
@@ -61,7 +61,7 @@
61- **设置Device侧应用类日志回传延时**:Ascend EP标准形态下,Device侧的slogd进程会将Device侧应用类日志自动回传到Host侧,使用户在Host侧可以直接查看Device侧的应用类日志。在业务进程退出前,系统有2000ms的默认延时将Device侧应用类日志回传到Host侧,超时后业务进程退出。未回传到Host侧的日志直接在Device侧落盘。可以通过环境变量ASCEND\_LOG\_DEVICE\_FLUSH\_TIMEOUT设置更高的Device侧应用类日志回传到Host侧的延时时间。61- **设置Device侧应用类日志回传延时**:Ascend EP标准形态下,Device侧的slogd进程会将Device侧应用类日志自动回传到Host侧,使用户在Host侧可以直接查看Device侧的应用类日志。在业务进程退出前,系统有2000ms的默认延时将Device侧应用类日志回传到Host侧,超时后业务进程退出。未回传到Host侧的日志直接在Device侧落盘。可以通过环境变量ASCEND\_LOG\_DEVICE\_FLUSH\_TIMEOUT设置更高的Device侧应用类日志回传到Host侧的延时时间。
62- **设置应用类日志目录(plog和device-id)下存储每个进程日志文件的数量**:`plog`和`device-id`日志目录下能够存储的单个进程回传的日志文件数量,默认为10个,该数量可以通过环境变量ASCEND\_HOST\_LOG\_FILE\_NUM进行设置。62- **设置应用类日志目录(plog和device-id)下存储每个进程日志文件的数量**:`plog`和`device-id`日志目录下能够存储的单个进程回传的日志文件数量,默认为10个,该数量可以通过环境变量ASCEND\_HOST\_LOG\_FILE\_NUM进行设置。
63- **指定日志拥塞处理方式**:在日志拥塞或IO访问性能差的情况下,为保证业务性能不劣化,系统可能会丢失日志。为便于问题定位,用户可通过ASCEND\_LOG\_SYNC\_SAVE配置在日志拥塞或IO访问性能差的情况下,不丢失日志。63- **指定日志拥塞处理方式**:在日志拥塞或IO访问性能差的情况下,为保证业务性能不劣化,系统可能会丢失日志。为便于问题定位,用户可通过ASCEND\_LOG\_SYNC\_SAVE配置在日志拥塞或IO访问性能差的情况下,不丢失日志。
64-- **设置日志展示方式**:日志的默认输出方式为将日志保存在log文件中,如果需要打印日志,可以配置环境变量ASCEND\_SLOG\_PRINT\_TO\_STDOUT。开启日志打印功能后,也可以在启动应用进程时,通过输出重定向方式将日志保存到指定文件中。例如:./main \> log.txt64+- **设置日志展示方式**:日志的默认输出方式为将日志保存在log文件中,如果需要打印日志,可以配置环境变量ASCEND\_LOG\_PRINT\_TO\_STDOUT。开启日志打印功能后,也可以在启动应用进程时,通过输出重定向方式将日志保存到指定文件中。例如:./main \> log.txt
65 65 
66注:如上环境变量详细信息请参考[《环境变量参考》](https://hiascend.com/document/redirect/CannCommunityEnvRef)。66注:如上环境变量详细信息请参考[《环境变量参考》](https://hiascend.com/document/redirect/CannCommunityEnvRef)。
67 67 
@@ -12,6 +12,7 @@
12#include <stdlib.h>12#include <stdlib.h>
13#include "dlog_core.h"13#include "dlog_core.h"
14#include "dlog_attr.h"14#include "dlog_attr.h"
15+#include "log_print.h"
15#include "mmpa_api.h"16#include "mmpa_api.h"
16 17 
17#ifdef __cplusplus18#ifdef __cplusplus
@@ -22,15 +23,74 @@ extern "C" {
22 * @brief : check env_stdout is enable or not, execute getenv only once23 * @brief : check env_stdout is enable or not, execute getenv only once
23 * @return : true enable; false disable24 * @return : true enable; false disable
24 */25 */
26+// stdout 开关取值缓冲区长度:合法值为 "0"/"1",预留冗余以识别非法长值。
27+// 取值长度 < 本值时告警可回显具体取值;>= 本值时 mmGetEnv 返回 EN_INVALID_PARAM,告警不回显取值。
28+#define STDOUT_ENV_VALUE_LEN 16U
29+ 
30+// stdout 开关环境变量名。集中定义,使读取与废弃告警共用同一来源,避免拼写不一致。
31+#define STDOUT_ENV_NAME "ASCEND_LOG_PRINT_TO_STDOUT"
32+#define STDOUT_ENV_NAME_DEPRECATED "ASCEND_SLOG_PRINT_TO_STDOUT"
33+ 
34+// 读取单个环境变量并判定 stdout 开关,输出维测日志。
35+// 使用 mmGetEnv 按名读取(值拷贝到调用者缓冲区),规避 getenv 返回内部指针在多线程下的竞争。
36+// replacementName 非 NULL 时,表示 envName 已废弃、应改用 replacementName,
37+// 在确认变量存在后先打印一次废弃告警;为 NULL 表示 envName 未废弃,不打印该告警。
38+// 注意:本参数用于旧变量兼容期,计划随旧变量在 13.0.0 版本一并移除,详见 DlogCheckEnvStdout 中的说明。
39+// 返回 true 表示该变量已配置,*enabled 为判定结果(1 开启/0 关闭);返回 false 表示未配置。
40+STATIC bool DlogGetStdoutEnv(const char* envName, const char* replacementName, int32_t* enabled)
41+{
42+ char envValue[STDOUT_ENV_VALUE_LEN] = {0};
43+ int32_t ret = mmGetEnv(envName, envValue, STDOUT_ENV_VALUE_LEN);
44+ if (ret == EN_ERROR) {
Z

级别:一般 问题机制:这里把 mmGetEnv 返回 EN_ERROR 一律当作“未配置”。但 Windows 版 mmGetEnv 在环境变量存在但缓冲区不足时也返回 EN_ERROR,这会把过长的新变量值误判为未设置。 影响:在 Windows 构建中,如果 ASCEND_LOG_PRINT_TO_STDOUT 配置为过长非法值且旧变量配置为 1,当前逻辑会继续回退旧变量并开启打屏,违背“新变量优先”和“非法值关闭”的行为,同时不会打印非法值告警。 修改建议:区分“未配置”和“读取失败或缓冲不足”。只有确认变量不存在时才返回 false;缓冲不足等已配置但非法的场景应设置 *enabled = 0 并返回 true。可同步调整 Windows 版 mmGetEnv 返回码,或在本函数内增加存在性判断,并补充对应用例。

likedislike
45+ return false; // 未配置
46+ }
47+ if (replacementName != NULL) {
48+ // 变量名由参数传入,函数内不硬编码具体变量名。
49+ // 告警不写死移除版本:移除版本由资料承载,避免版本调整需同步改代码。
50+ SELF_LOG_WARN("Environment variable '%s' is deprecated; use '%s' instead.", envName, replacementName);
51+ }
52+ if (ret != EN_OK) {
53+ // 已配置但取值过长/异常 → 非法值(缓冲区未取到值,不回显)
54+ SELF_LOG_WARN(
55+ "Invalid value for environment variable '%s'; expected '0' or '1'. "
56+ "Log-to-stdout disabled.",
57+ envName);
58+ *enabled = 0;
59+ return true;
60+ }
61+ if (strcmp(envValue, "1") == 0) {
62+ SELF_LOG_INFO("Log-to-stdout enabled by environment variable '%s'.", envName);
63+ *enabled = 1;
64+ } else if (strcmp(envValue, "0") == 0) {
65+ *enabled = 0; // 显式关闭即默认行为,保持静默
66+ } else {
67+ SELF_LOG_WARN(
68+ "Invalid value '%s' for environment variable '%s'; expected '0' or '1'. "
69+ "Log-to-stdout disabled.",
70+ envValue, envName);
71+ *enabled = 0;
72+ }
73+ return true;
74+}
zhangjie
zhangjiezhangjie7月31日

级别:提示 问题:static int32_t stdoutFlag 的读-判断-写序列无同步保护。若 DlogCheckEnvStdout 首次调用时多线程并发进入,各线程可能同时执行 mmGetEnv 和 SELF_LOG_*,导致废弃告警或非法值告警重复打印多次。 影响:告警日志可能出现重复,不影响最终 stdoutFlag 收敛结果的正确性,但维测体验下降。此为存量问题,本次重构未改善。 修复建议:若性能允许,可在写入 stdoutFlag 后对 stderrFlag 使用 __atomic 或 mmpa 原子操作/CAS 保证单次求值;或将求值提前到初始化阶段完成。

likedislike
GuoWenbo
8月4日 评论:
75+ 
25bool DlogCheckEnvStdout(void)76bool DlogCheckEnvStdout(void)
26{77{
zhangjie
zhangjiezhangjie7月31日

级别:提示 问题:环境变量名使用裸字符串 "ASCEND_LOG_PRINT_TO_STDOUT" / "ASCEND_SLOG_PRINT_TO_STDOUT",旧代码中已有 MM_ENV_ASCEND_SLOG_PRINT_TO_STDOUT 宏定义。 影响:字符串拼写错误难以在编译期发现,后续若需改名或迁移需多处修改。 修复建议:在对应头文件中新增 MM_ENV_ASCEND_LOG_PRINT_TO_STDOUT 宏定义,并在 DlogGetStdoutEnv 调用处引用宏而非硬编码字符串。

likedislike
GuoWenbo
8月4日 评论:
27 static int32_t stdoutFlag = -1;78 static int32_t stdoutFlag = -1;
28- if (stdoutFlag == -1) { 79+ if (stdoutFlag == -1) {
29- const char *envres = NULL;80+ int32_t enabled = 0;
30- MM_SYS_GET_ENV(MM_ENV_ASCEND_SLOG_PRINT_TO_STDOUT, (envres));81+ // 新变量优先:ASCEND_LOG_PRINT_TO_STDOUT(未废弃,故 replacementName 传 NULL)
31- if ((envres != NULL) && (strcmp(envres, "1") == 0)) {82+ if (DlogGetStdoutEnv(STDOUT_ENV_NAME, NULL, &enabled)) {
32- stdoutFlag = 1;83+ stdoutFlag = enabled;
84+ } else if (DlogGetStdoutEnv(STDOUT_ENV_NAME_DEPRECATED, STDOUT_ENV_NAME, &enabled)) {
85+ // 新变量未配置时回退旧变量(兼容期保留),并提示废弃。
86+ //
87+ // 旧变量 ASCEND_SLOG_PRINT_TO_STDOUT 在 CANN 9.2.0 标记废弃,计划在 13.0.0 版本
88+ // 随资料一并删除。届时应移除本回退分支、STDOUT_ENV_NAME_DEPRECATED 宏及其废弃
89+ // 告警,并同步清理相关 UT(TC-768-003/007/009 等依赖旧变量的用例)。
90+ // 注意:删除后旧变量将不再生效,属预期的不兼容变更,需在版本说明中明确告知。
91+ stdoutFlag = enabled;
33 } else {92 } else {
93+ // 两者均未配置:默认关闭,保持静默
34 stdoutFlag = 0;94 stdoutFlag = 0;
35 }95 }
36 }96 }
@@ -41,13 +101,13 @@ bool DlogCheckEnvStdout(void)
41 * @brief : write to console101 * @brief : write to console
42 * @param [in] : logMsg struct of log message102 * @param [in] : logMsg struct of log message
43 */103 */
44-void DlogWriteToConsole(LogMsg *logMsg)104+void DlogWriteToConsole(LogMsg* logMsg)
45{105{
46#ifndef _LOG_UT106#ifndef _LOG_UT
47 DlogSetMessageNl(logMsg);107 DlogSetMessageNl(logMsg);
48 int32_t fd = ToolFileno(stdout);108 int32_t fd = ToolFileno(stdout);
49 ONE_ACT_ERR_LOG(fd <= 0, return, "file_handle is invalid, file_handle=%d.", fd);109 ONE_ACT_ERR_LOG(fd <= 0, return, "file_handle is invalid, file_handle=%d.", fd);
50- (void)ToolWrite(fd, (void *)logMsg->logContent, logMsg->contentLength);110+ (void)ToolWrite(fd, (void*)logMsg->logContent, logMsg->contentLength);
51#else111#else
52 return;112 return;
53#endif113#endif
@@ -31,14 +31,13 @@ using namespace testing;
31#include "log_file_util.h"31#include "log_file_util.h"
32 32 
33extern "C" {33extern "C" {
34- void DllMain(void);34+void DllMain(void);
35- void DlogFree(void);35+void DlogFree(void);
36- void PlogDriverLog(int32_t moduleId, int32_t level, const char *fmt, ...);36+void PlogDriverLog(int32_t moduleId, int32_t level, const char* fmt, ...);
37- void DlogInitServerType(void);37+void DlogInitServerType(void);
38}38}
39 39 
40-class EP_ALOG_HOST_EXCP_UTEST : public testing::Test40+class EP_ALOG_HOST_EXCP_UTEST : public testing::Test {
41-{
42protected:41protected:
43 virtual void SetUp()42 virtual void SetUp()
44 {43 {
@@ -83,22 +82,16 @@ public:
83 (void)ProcessLogFree();82 (void)ProcessLogFree();
84 DlogFree();83 DlogFree();
85 }84 }
86- bool DlogCheckPrint()85+ bool DlogCheckPrint() {}
87- {86+ bool DlogCheckPrintNum() {}
88- }87+ bool DlogCheckFileValue() {}
89- bool DlogCheckPrintNum()
90- {
91- }
92- bool DlogCheckFileValue()
93- {
94- }
95};88};
96 89 
97// init host file list failed(malloc failed)90// init host file list failed(malloc failed)
98TEST_F(EP_ALOG_HOST_EXCP_UTEST, PlogFileMgrInitHostFailed)91TEST_F(EP_ALOG_HOST_EXCP_UTEST, PlogFileMgrInitHostFailed)
99{92{
100- void *space = malloc(TOOL_MAX_PATH + 1);93+ void* space = malloc(TOOL_MAX_PATH + 1);
101- MOCKER(LogMalloc).stubs().will(repeat(space, 4)).then(returnValue((void *)NULL));94+ MOCKER(LogMalloc).stubs().will(repeat(space, 4)).then(returnValue((void*)NULL));
102 MOCKER(LogFree).expects(exactly(4));95 MOCKER(LogFree).expects(exactly(4));
103 setenv("ASCEND_PROCESS_LOG_PATH", PATH_ROOT, 1);96 setenv("ASCEND_PROCESS_LOG_PATH", PATH_ROOT, 1);
104 EXPECT_EQ(LOG_FAILURE, PlogFileMgrInit());97 EXPECT_EQ(LOG_FAILURE, PlogFileMgrInit());
@@ -123,7 +116,7 @@ TEST_F(EP_ALOG_HOST_EXCP_UTEST, PlogFileMgrInitHostFailedNoPemission)
123 GlobalMockObject::verify();116 GlobalMockObject::verify();
124 ResetErrLog();117 ResetErrLog();
125 118 
126- char path[256] = { 0 };119+ char path[256] = {0};
127 (void)sprintf_s(path, 256, "%s/log", PATH_ROOT);120 (void)sprintf_s(path, 256, "%s/log", PATH_ROOT);
128 setenv("ASCEND_PROCESS_LOG_PATH", path, 1);121 setenv("ASCEND_PROCESS_LOG_PATH", path, 1);
129 EXPECT_EQ(LOG_SUCCESS, PlogFileMgrInit());122 EXPECT_EQ(LOG_SUCCESS, PlogFileMgrInit());
@@ -228,6 +221,7 @@ TEST_F(EP_ALOG_HOST_EXCP_UTEST, plog_buffer_init_failed)
228// getenv ASCEND_SLOG_PRINT_TO_STDOUT only once221// getenv ASCEND_SLOG_PRINT_TO_STDOUT only once
229TEST_F(EP_ALOG_HOST_EXCP_UTEST, dlog_check_env_stdout)222TEST_F(EP_ALOG_HOST_EXCP_UTEST, dlog_check_env_stdout)
230{223{
224+ unsetenv("ASCEND_LOG_PRINT_TO_STDOUT");
231 unsetenv("ASCEND_SLOG_PRINT_TO_STDOUT");225 unsetenv("ASCEND_SLOG_PRINT_TO_STDOUT");
232 bool ret = DlogCheckEnvStdout();226 bool ret = DlogCheckEnvStdout();
233 EXPECT_EQ(false, ret);227 EXPECT_EQ(false, ret);
@@ -236,6 +230,211 @@ TEST_F(EP_ALOG_HOST_EXCP_UTEST, dlog_check_env_stdout)
236 EXPECT_EQ(false, ret);230 EXPECT_EQ(false, ret);
237}231}
238 232 
233+// ---------------------------------------------------------------------------
234+// issue #768: ASCEND_SLOG_PRINT_TO_STDOUT 改名为 ASCEND_LOG_PRINT_TO_STDOUT
235+// DlogCheckEnvStdout 使用 static 缓存,仅首次求值,因此每个分支必须在独立进程
236+// (threadsafe death test 会重新 exec 测试二进制) 中验证,避免缓存跨用例污染。
237+// ---------------------------------------------------------------------------
238+ 
239+// 自维测日志 (SELF_LOG_INFO/WARN) 在 UT 下经 self_log_stub 落到 PATH_ROOT/LogFile.txt
240+static bool Issue768SelfLogHas(const char* substr)
241+{
zhangjie
zhangjiezhangjie7月31日

级别:一般 问题:缺少对 DlogGetStdoutEnv 中 ret != EN_OK 分支(环境变量值长度超过 STDOUT_ENV_VALUE_LEN-1 的缓冲区)的测试覆盖。该分支产生独立的 WARN 日志且不回显值,与 else 分支行为不同。 影响:值过长这一边界场景未经验证,若 mmGetEnv 返回码语义变化或截断处理有误,缺陷无法被测试发现。 修复建议:增加一个 death test 用例,设置 ASCEND_LOG_PRINT_TO_STDOUT 为 16+ 字符长值(如 "1111111111111111"),验证返回 false、WARN 日志中出现 'expected 0 or 1' 且不包含回显的非法值字符串。

likedislike
GuoWenbo
8月4日 评论:
242+ char cmd[600] = {0};
243+ (void)snprintf_s(cmd, sizeof(cmd), sizeof(cmd) - 1U, "grep -a -q \"%s\" %s/LogFile.txt", substr, PATH_ROOT);
244+ return system(cmd) == 0;
245+}
246+ 
247+// 白盒分支:校验返回值 + 各维测日志(废弃告警 / 开启 INFO / 非法值 WARN)是否符合预期。
248+// 返回 0 表示全部符合,非 0 表示某项不符(便于死亡测试退出码定位)。
249+static int Issue768ScenarioCheckStdout(
250+ const char* newVal, const char* oldVal, bool expectEnabled, bool expectDeprecatedWarn, bool expectEnableInfo,
251+ bool expectInvalidWarn)
252+{
253+ unsetenv("ASCEND_LOG_PRINT_TO_STDOUT");
254+ unsetenv("ASCEND_SLOG_PRINT_TO_STDOUT");
255+ if (newVal != nullptr) {
256+ setenv("ASCEND_LOG_PRINT_TO_STDOUT", newVal, 1);
257+ }
258+ if (oldVal != nullptr) {
259+ setenv("ASCEND_SLOG_PRINT_TO_STDOUT", oldVal, 1);
260+ }
261+ bool enabled = DlogCheckEnvStdout();
262+ if (enabled != expectEnabled) {
263+ return 1;
264+ }
265+ // 废弃告警:仅在回退旧变量时出现
266+ if (Issue768SelfLogHas("'ASCEND_SLOG_PRINT_TO_STDOUT' is deprecated") != expectDeprecatedWarn) {
267+ return 2;
268+ }
269+ // 开启 INFO:值为 "1" 生效时出现
270+ if (Issue768SelfLogHas("Log-to-stdout enabled by environment variable") != expectEnableInfo) {
271+ return 3;
272+ }
273+ // 非法值 WARN
274+ if (Issue768SelfLogHas("expected '0' or '1'. Log-to-stdout disabled") != expectInvalidWarn) {
275+ return 4;
276+ }
zhangjie
zhangjiezhangjie7月31日

级别:一般 问题:Issue768RunStdoutE2eScenario 在调用 ProcessLogInit 前未清理 PATH_ROOT/debug 目录,若该目录因前序用例残留而存在,access 检查将得到假阳性结果。 影响:当 stdout 开启(expectStdout=true)时,残留的 debug 目录会导致返回 1(失败),造成 TC-768-101/102 等用例间歇性失败或误通过。 修复建议:在 setenv 之后、DllMain 之前增加清理逻辑,如 system("rm -rf PATH_ROOT/debug"),确保每次 E2E 场景起始状态干净。

likedislike
GuoWenbo
8月4日 评论:
277+ return 0;
278+}
279+ 
280+// 长值分支:取值长度 >= STDOUT_ENV_VALUE_LEN 时 mmGetEnv 返回 EN_INVALID_PARAM,
281+// 走"不回显取值"的非法值告警分支(区别于回显取值的 else 分支)。
282+// 校验:关闭打屏 + 该告警出现 + 过长取值未被回显。
283+static int Issue768ScenarioCheckStdoutLongValue(const char* envName, const char* longVal)
284+{
285+ unsetenv("ASCEND_LOG_PRINT_TO_STDOUT");
286+ unsetenv("ASCEND_SLOG_PRINT_TO_STDOUT");
287+ setenv(envName, longVal, 1);
288+ if (DlogCheckEnvStdout() != false) {
289+ return 1;
290+ }
291+ // 不回显取值的非法值告警:"Invalid value for environment variable '<name>'; expected ..."
292+ if (!Issue768SelfLogHas("Invalid value for environment variable")) {
293+ return 2;
294+ }
295+ // 缓冲区未取到值,过长取值不得出现在告警中
296+ if (Issue768SelfLogHas(longVal)) {
297+ return 3;
298+ }
299+ return 0;
300+}
301+ 
302+// 二进制端到端:通过 dlog 打印接口,按环境变量确认日志落盘 vs 打屏。
303+// 打屏开启时日志走 console,不会在 PATH_ROOT/debug 落盘目录产生文件。返回 0 符合预期。
304+static int Issue768RunStdoutE2eScenario(const char* newVal, const char* oldVal, bool expectStdout)
305+{
306+ unsetenv("ASCEND_LOG_PRINT_TO_STDOUT");
307+ unsetenv("ASCEND_SLOG_PRINT_TO_STDOUT");
308+ if (newVal != nullptr) {
309+ setenv("ASCEND_LOG_PRINT_TO_STDOUT", newVal, 1);
310+ }
311+ if (oldVal != nullptr) {
312+ setenv("ASCEND_SLOG_PRINT_TO_STDOUT", oldVal, 1);
313+ }
314+ setenv("ASCEND_GLOBAL_LOG_LEVEL", "0", 1);
315+ setenv("ASCEND_PROCESS_LOG_PATH", PATH_ROOT, 1);
316+ DllMain();
317+ (void)ProcessLogInit();
318+ dlog_error(SLOG | DEBUG_LOG_MASK, "[EP_ALOG_HOST_EXCP_UTEST][issue768] e2e stdout switch test.");
319+ (void)ProcessLogFree();
320+ DlogFree();
321+ unsetenv("ASCEND_GLOBAL_LOG_LEVEL");
322+ unsetenv("ASCEND_PROCESS_LOG_PATH");
323+ bool diskExists = (access(PATH_ROOT "/debug", F_OK) == 0);
324+ if (expectStdout) {
325+ return diskExists ? 1 : 0; // 打屏开启:不落盘 debug
326+ }
327+ return diskExists ? 0 : 1; // 打屏关闭:按默认落盘
328+}
329+ 
330+// 参数:(new, old, expectEnabled, expectDeprecatedWarn, expectEnableInfo, expectInvalidWarn)
331+// TC-768-001 新变量=1 开启:开启 INFO,无废弃/无非法
332+TEST_F(EP_ALOG_HOST_EXCP_UTEST, dlog_check_env_stdout_new_env_on)
333+{
334+ testing::GTEST_FLAG(death_test_style) = "threadsafe";
335+ EXPECT_EXIT(
336+ std::exit(Issue768ScenarioCheckStdout("1", nullptr, true, false, true, false)), testing::ExitedWithCode(0), "");
337+}
338+ 
339+// TC-768-002 新变量=0 显式关闭:静默(无任何维测日志)
340+TEST_F(EP_ALOG_HOST_EXCP_UTEST, dlog_check_env_stdout_new_env_off_silent)
341+{
342+ testing::GTEST_FLAG(death_test_style) = "threadsafe";
343+ EXPECT_EXIT(
344+ std::exit(Issue768ScenarioCheckStdout("0", nullptr, false, false, false, false)), testing::ExitedWithCode(0),
345+ "");
346+}
347+ 
348+// TC-768-003 仅旧变量=1,兼容开启:废弃 WARN + 开启 INFO
349+TEST_F(EP_ALOG_HOST_EXCP_UTEST, dlog_check_env_stdout_old_env_compat)
350+{
351+ testing::GTEST_FLAG(death_test_style) = "threadsafe";
352+ EXPECT_EXIT(
353+ std::exit(Issue768ScenarioCheckStdout(nullptr, "1", true, true, true, false)), testing::ExitedWithCode(0), "");
354+}
355+ 
356+// TC-768-004 新变量=0 且旧变量=1,新变量优先关闭(不回退旧变量、无废弃告警、无开启 INFO)
357+TEST_F(EP_ALOG_HOST_EXCP_UTEST, dlog_check_env_stdout_new_env_priority)
358+{
359+ testing::GTEST_FLAG(death_test_style) = "threadsafe";
360+ EXPECT_EXIT(
361+ std::exit(Issue768ScenarioCheckStdout("0", "1", false, false, false, false)), testing::ExitedWithCode(0), "");
362+}
363+ 
364+// TC-768-005 两变量均未配置,默认关闭:静默
365+TEST_F(EP_ALOG_HOST_EXCP_UTEST, dlog_check_env_stdout_default_off)
366+{
367+ testing::GTEST_FLAG(death_test_style) = "threadsafe";
368+ EXPECT_EXIT(
369+ std::exit(Issue768ScenarioCheckStdout(nullptr, nullptr, false, false, false, false)),
370+ testing::ExitedWithCode(0), "");
371+}
372+ 
373+// TC-768-006 新变量为非法值,关闭:非法值 WARN,无废弃/无开启 INFO
374+TEST_F(EP_ALOG_HOST_EXCP_UTEST, dlog_check_env_stdout_new_env_invalid)
375+{
376+ testing::GTEST_FLAG(death_test_style) = "threadsafe";
377+ EXPECT_EXIT(
378+ std::exit(Issue768ScenarioCheckStdout("abc", nullptr, false, false, false, true)), testing::ExitedWithCode(0),
379+ "");
380+}
381+ 
382+// TC-768-007 旧变量为非法值(新变量未设):废弃 WARN + 非法值 WARN,关闭
383+TEST_F(EP_ALOG_HOST_EXCP_UTEST, dlog_check_env_stdout_old_env_invalid)
384+{
385+ testing::GTEST_FLAG(death_test_style) = "threadsafe";
386+ EXPECT_EXIT(
387+ std::exit(Issue768ScenarioCheckStdout(nullptr, "xyz", false, true, false, true)), testing::ExitedWithCode(0),
388+ "");
389+}
390+ 
391+// TC-768-008 新变量取值过长(16 字符 >= STDOUT_ENV_VALUE_LEN):
392+// mmGetEnv 返回 EN_INVALID_PARAM,走不回显取值的非法值告警分支,关闭打屏
393+TEST_F(EP_ALOG_HOST_EXCP_UTEST, dlog_check_env_stdout_new_env_value_too_long)
394+{
395+ testing::GTEST_FLAG(death_test_style) = "threadsafe";
396+ EXPECT_EXIT(
397+ std::exit(Issue768ScenarioCheckStdoutLongValue("ASCEND_LOG_PRINT_TO_STDOUT", "1111111111111111")),
398+ testing::ExitedWithCode(0), "");
399+}
400+ 
401+// TC-768-009 旧变量取值过长(新变量未设):回退旧变量后同样走不回显取值的非法值告警分支
402+TEST_F(EP_ALOG_HOST_EXCP_UTEST, dlog_check_env_stdout_old_env_value_too_long)
403+{
404+ testing::GTEST_FLAG(death_test_style) = "threadsafe";
405+ EXPECT_EXIT(
406+ std::exit(Issue768ScenarioCheckStdoutLongValue("ASCEND_SLOG_PRINT_TO_STDOUT", "1111111111111111")),
407+ testing::ExitedWithCode(0), "");
408+}
409+ 
410+// TC-768-101 新变量=1,日志打屏(不落盘)
411+TEST_F(EP_ALOG_HOST_EXCP_UTEST, dlog_e2e_new_env_stdout)
412+{
413+ testing::GTEST_FLAG(death_test_style) = "threadsafe";
414+ EXPECT_EXIT(std::exit(Issue768RunStdoutE2eScenario("1", nullptr, true)), testing::ExitedWithCode(0), "");
415+}
416+ 
417+// TC-768-102 仅旧变量=1,兼容打屏(不落盘)
418+TEST_F(EP_ALOG_HOST_EXCP_UTEST, dlog_e2e_old_env_compat_stdout)
419+{
420+ testing::GTEST_FLAG(death_test_style) = "threadsafe";
421+ EXPECT_EXIT(std::exit(Issue768RunStdoutE2eScenario(nullptr, "1", true)), testing::ExitedWithCode(0), "");
422+}
423+ 
424+// TC-768-103 两变量均未配置,日志默认落盘(不打屏)
425+TEST_F(EP_ALOG_HOST_EXCP_UTEST, dlog_e2e_default_to_file)
426+{
427+ testing::GTEST_FLAG(death_test_style) = "threadsafe";
428+ EXPECT_EXIT(std::exit(Issue768RunStdoutE2eScenario(nullptr, nullptr, false)), testing::ExitedWithCode(0), "");
429+}
430+ 
431+// TC-768-104 新变量=0 且旧变量=1,新变量优先,日志落盘(不打屏)
432+TEST_F(EP_ALOG_HOST_EXCP_UTEST, dlog_e2e_new_env_priority_to_file)
433+{
434+ testing::GTEST_FLAG(death_test_style) = "threadsafe";
435+ EXPECT_EXIT(std::exit(Issue768RunStdoutE2eScenario("0", "1", false)), testing::ExitedWithCode(0), "");
436+}
437+ 
239TEST_F(EP_ALOG_HOST_EXCP_UTEST, AlogInterfaceError)438TEST_F(EP_ALOG_HOST_EXCP_UTEST, AlogInterfaceError)
240{439{
241 AlogRecord(SLOG, DLOG_TYPE_DEBUG, DLOG_ERROR, nullptr);440 AlogRecord(SLOG, DLOG_TYPE_DEBUG, DLOG_ERROR, nullptr);
@@ -243,7 +442,7 @@ TEST_F(EP_ALOG_HOST_EXCP_UTEST, AlogInterfaceError)
243 EXPECT_EQ(0, AlogCheckDebugLevel(0, -1));442 EXPECT_EQ(0, AlogCheckDebugLevel(0, -1));
244}443}
245 444 
246-static void CallInvalidAcllogVaList(int32_t moduleId, int32_t level, const char *fmt, ...)445+static void CallInvalidAcllogVaList(int32_t moduleId, int32_t level, const char* fmt, ...)
247{446{
248 va_list list;447 va_list list;
249 va_start(list, fmt);448 va_start(list, fmt);
@@ -292,9 +491,9 @@ TEST_F(EP_ALOG_HOST_EXCP_UTEST, DlogInvalidModuleId)
292 DlogDestructor();491 DlogDestructor();
293 unsetenv("ASCEND_GLOBAL_LOG_LEVEL");492 unsetenv("ASCEND_GLOBAL_LOG_LEVEL");
294 unsetenv("ASCEND_PROCESS_LOG_PATH");493 unsetenv("ASCEND_PROCESS_LOG_PATH");
295- EXPECT_NE(0, access(PATH_ROOT "/debug",F_OK));494+ EXPECT_NE(0, access(PATH_ROOT "/debug", F_OK));
296- EXPECT_NE(0, access(PATH_ROOT "/run",F_OK));495+ EXPECT_NE(0, access(PATH_ROOT "/run", F_OK));
297- EXPECT_NE(0, access(PATH_ROOT "/security",F_OK));496+ EXPECT_NE(0, access(PATH_ROOT "/security", F_OK));
298}497}
299 498 
300TEST_F(EP_ALOG_HOST_EXCP_UTEST, DlogInitServerType)499TEST_F(EP_ALOG_HOST_EXCP_UTEST, DlogInitServerType)
@@ -307,7 +506,6 @@ TEST_F(EP_ALOG_HOST_EXCP_UTEST, DlogInitServerType)
307 DlogInitServerType();506 DlogInitServerType();
308 EXPECT_EQ(false, DlogIsPoolingDevice());507 EXPECT_EQ(false, DlogIsPoolingDevice());
309 508 
310- 
311 ReSetServerType();509 ReSetServerType();
312 DlogInitServerType();510 DlogInitServerType();
313}511}
@@ -320,7 +518,9 @@ TEST_F(EP_ALOG_HOST_EXCP_UTEST, PlogOpenNoPemission)
320 DlogConstructor();518 DlogConstructor();
321 519 
322 MOCKER(ToolOpenWithMode).stubs().will(returnValue(-1));520 MOCKER(ToolOpenWithMode).stubs().will(returnValue(-1));
323- dlog_error(SLOG | DEBUG_LOG_MASK, "[EP_ALOG_HOST_EXCP_UTEST][DlogPrint_HostLogBuffFull] test for mask_debug, error_level.");521+ dlog_error(
522+ SLOG | DEBUG_LOG_MASK,
523+ "[EP_ALOG_HOST_EXCP_UTEST][DlogPrint_HostLogBuffFull] test for mask_debug, error_level.");
324 524 
325 // 释放525 // 释放
326 DlogDestructor();526 DlogDestructor();
@@ -336,7 +536,9 @@ TEST_F(EP_ALOG_HOST_EXCP_UTEST, PlogWriteNoPemission)
336 DlogConstructor();536 DlogConstructor();
337 537 
338 MOCKER(ToolWrite).stubs().will(returnValue(-1));538 MOCKER(ToolWrite).stubs().will(returnValue(-1));
339- dlog_error(SLOG | DEBUG_LOG_MASK, "[EP_ALOG_HOST_EXCP_UTEST][DlogPrint_HostLogBuffFull] test for mask_debug, error_level.");539+ dlog_error(
540+ SLOG | DEBUG_LOG_MASK,
541+ "[EP_ALOG_HOST_EXCP_UTEST][DlogPrint_HostLogBuffFull] test for mask_debug, error_level.");
340 542 
341 // 释放543 // 释放
342 DlogDestructor();544 DlogDestructor();
@@ -352,7 +554,9 @@ TEST_F(EP_ALOG_HOST_EXCP_UTEST, PlogMkdirNoPemission)
352 DlogConstructor();554 DlogConstructor();
353 555 
354 MOCKER(LogMkdirRecur).stubs().will(returnValue(1));556 MOCKER(LogMkdirRecur).stubs().will(returnValue(1));
355- dlog_error(SLOG | DEBUG_LOG_MASK, "[EP_ALOG_HOST_EXCP_UTEST][DlogPrint_HostLogBuffFull] test for mask_debug, error_level.");557+ dlog_error(
558+ SLOG | DEBUG_LOG_MASK,
559+ "[EP_ALOG_HOST_EXCP_UTEST][DlogPrint_HostLogBuffFull] test for mask_debug, error_level.");
356 560 
357 // 释放561 // 释放
358 DlogDestructor();562 DlogDestructor();