| @@ -173,7 +173,7 @@ echo -e "\n=== 分析完成 ===" | |||
| 173 | ```bash | 173 | ```bash |
| 174 | # 设置日志级别(环境变量方式) | 174 | # 设置日志级别(环境变量方式) |
| 175 | export ASCEND_GLOBAL_LOG_LEVEL=0 # DEBUG级别,输出最详细日志 | 175 | export 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 | # 或在代码中设置 |
| 179 | aclError error = aclInit(nullptr); | 179 | aclError error = aclInit(nullptr); |
| @@ -1,4 +1,4 @@ | |||
| 1 | -# ASCEND\_SLOG\_PRINT\_TO\_STDOUT | 1 | +# 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 | ```sh | 20 | ```sh |
| 21 | -export ASCEND_SLOG_PRINT_TO_STDOUT=1 | 21 | +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 | |||
| 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.txt | 64 | +- **设置日志展示方式**:日志的默认输出方式为将日志保存在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 | 12 | ||
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | + | ||
| 15 | 16 | ||
| 16 | 17 | ||
| 17 | 18 | ||
| @@ -22,15 +23,74 @@ extern "C" { | |||
| 22 | * @brief : check env_stdout is enable or not, execute getenv only once | 23 | * @brief : check env_stdout is enable or not, execute getenv only once |
| 23 | * @return : true enable; false disable | 24 | * @return : true enable; false disable |
| 24 | */ | 25 | */ |
| 26 | +// stdout 开关取值缓冲区长度:合法值为 "0"/"1",预留冗余以识别非法长值。 | ||
| 27 | +// 取值长度 < 本值时告警可回显具体取值;>= 本值时 mmGetEnv 返回 EN_INVALID_PARAM,告警不回显取值。 | ||
| 28 | + | ||
| 29 | + | ||
| 30 | +// stdout 开关环境变量名。集中定义,使读取与废弃告警共用同一来源,避免拼写不一致。 | ||
| 31 | + | ||
| 32 | + | ||
| 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 级别:一般
问题机制:这里把 ![]() ![]() | |||
| 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 | +} | ||
级别:提示 问题:static int32_t stdoutFlag 的读-判断-写序列无同步保护。若 DlogCheckEnvStdout 首次调用时多线程并发进入,各线程可能同时执行 mmGetEnv 和 SELF_LOG_*,导致废弃告警或非法值告警重复打印多次。 影响:告警日志可能出现重复,不影响最终 stdoutFlag 收敛结果的正确性,但维测体验下降。此为存量问题,本次重构未改善。 修复建议:若性能允许,可在写入 stdoutFlag 后对 stderrFlag 使用 __atomic 或 mmpa 原子操作/CAS 保证单次求值;或将求值提前到初始化阶段完成。 ![]() ![]() | |||
| 75 | + | ||
| 25 | bool DlogCheckEnvStdout(void) | 76 | bool DlogCheckEnvStdout(void) |
| 26 | { | 77 | { |
级别:提示 问题:环境变量名使用裸字符串 "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 调用处引用宏而非硬编码字符串。 ![]() ![]() | |||
| 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 console | 101 | * @brief : write to console |
| 42 | * @param [in] : logMsg struct of log message | 102 | * @param [in] : logMsg struct of log message |
| 43 | */ | 103 | */ |
| 44 | -void DlogWriteToConsole(LogMsg *logMsg) | 104 | +void DlogWriteToConsole(LogMsg* logMsg) |
| 45 | { | 105 | { |
| 46 | 106 | ||
| 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 | 111 | ||
| 52 | return; | 112 | return; |
| 53 | 113 | ||
| @@ -31,14 +31,13 @@ using namespace testing; | |||
| 31 | 31 | ||
| 32 | 32 | ||
| 33 | extern "C" { | 33 | extern "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::Test | 40 | +class EP_ALOG_HOST_EXCP_UTEST : public testing::Test { |
| 41 | -{ | ||
| 42 | protected: | 41 | protected: |
| 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) |
| 98 | TEST_F(EP_ALOG_HOST_EXCP_UTEST, PlogFileMgrInitHostFailed) | 91 | TEST_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 once | 221 | // getenv ASCEND_SLOG_PRINT_TO_STDOUT only once |
| 229 | TEST_F(EP_ALOG_HOST_EXCP_UTEST, dlog_check_env_stdout) | 222 | TEST_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 | +{ | ||
级别:一般 问题:缺少对 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' 且不包含回显的非法值字符串。 ![]() ![]() | |||
| 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 | + } | ||
级别:一般 问题:Issue768RunStdoutE2eScenario 在调用 ProcessLogInit 前未清理 PATH_ROOT/debug 目录,若该目录因前序用例残留而存在,access 检查将得到假阳性结果。 影响:当 stdout 开启(expectStdout=true)时,残留的 debug 目录会导致返回 1(失败),造成 TC-768-101/102 等用例间歇性失败或误通过。 修复建议:在 setenv 之后、DllMain 之前增加清理逻辑,如 system("rm -rf PATH_ROOT/debug"),确保每次 E2E 场景起始状态干净。 ![]() ![]() | |||
| 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 | + | ||
| 239 | TEST_F(EP_ALOG_HOST_EXCP_UTEST, AlogInterfaceError) | 438 | TEST_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 | ||
| 300 | TEST_F(EP_ALOG_HOST_EXCP_UTEST, DlogInitServerType) | 499 | TEST_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(); |


【一般】【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