* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include <cstdlib>
#include <string>
#include <cstring>
#include <unordered_map>
#include <iostream>
#include <algorithm>
#include "utils/env.h"
#include "log/log_sink_stdout_sip.h"
#include "log/log_sink_file_sip.h"
#include "log/log.h"
#include "log/log_core_sip.h"
namespace AsdSip {
static bool GetLogToStdoutFromEnv()
{
const char *envLogToStdout = std::getenv("ASCEND_SLOG_PRINT_TO_STDOUT");
return envLogToStdout != nullptr && strlen(envLogToStdout) <= MAX_ENV_STRING_LEN &&
strcmp(envLogToStdout, "1") == 0;
}
static bool GetLogToFileFromEnv()
{
const char *envLogToFile = std::getenv("ASCEND_PROCESS_LOG_PATH");
return envLogToFile != nullptr && strlen(envLogToFile) <= MAX_ENV_STRING_LEN;
}
static LogLevel GetLogLevelFromEnv()
{
取值为:
0:对应DEBUG级别。
1:对应INFO级别。
2:对应WARNING级别。
3:对应ERROR级别,默认为ERROR级别。
4:对应NULL级别,不输出日志。
其他值为非法值。 */
const char *env = std::getenv("ASCEND_GLOBAL_LOG_LEVEL");
if (env == nullptr || strlen(env) > MAX_ENV_STRING_LEN) {
return LogLevel::ERROR;
}
std::string envLogLevel(env);
std::transform(envLogLevel.begin(), envLogLevel.end(), envLogLevel.begin(), ::toupper);
static std::unordered_map<std::string, LogLevel> levelMap{{"0", LogLevel::DEBUG},
{"1", LogLevel::INFO},
{"2", LogLevel::WARN},
{"3", LogLevel::ERROR},
{"4", LogLevel::FATAL}};
auto levelIt = levelMap.find(envLogLevel);
return levelIt != levelMap.end() ? levelIt->second : LogLevel::ERROR;
}
static std::vector<std::string> splitString(const std::string &s, char delimiter)
{
std::vector<std::string> tokens;
std::string token;
std::istringstream tokenStream(s);
while (std::getline(tokenStream, token, delimiter)) {
tokens.push_back(token);
}
return tokens;
}
static LogLevel GetModuleLogLevelFromEnv(bool &isSet)
{
格式为:export ASCEND_MODULE_LOG_LEVEL=module_name=module_level
module_name:为模块名,支持设置为GE、ASCENDCL、DRV、RUNTIME等,详细请参见CANN软件安装目录/include/base/log_types.h。
module_level:为对应模块的日志级别,支持设置为如下值。
0:对应DEBUG级别。
1:对应INFO级别。
2:对应WARNING级别。
3:对应ERROR级别,默认为ERROR级别。
4:对应NULL级别,不输出日志。
其他值为非法值。 */
const char *env = std::getenv("ASCEND_MODULE_LOG_LEVEL");
if (env == nullptr || strlen(env) > MAX_ENV_STRING_LEN) {
isSet = false;
return LogLevel::ERROR;
}
std::string envs(env);
std::vector<std::string> envLogLevels = splitString(envs, ':');
std::string envLogLevel = "-1";
for (const auto &i : envLogLevels) {
std::vector<std::string> key_value = splitString(i, '=');
if (key_value.size() >= 1) {
if (key_value[0] == "OP") {
if (key_value.size() == 2) {
isSet = true;
envLogLevel = key_value[1];
}
break;
}
}
}
if (!isSet) {
return LogLevel::ERROR;
}
static std::unordered_map<std::string, LogLevel> levelMap{{"0", LogLevel::DEBUG},
{"1", LogLevel::INFO},
{"2", LogLevel::WARN},
{"3", LogLevel::ERROR},
{"4", LogLevel::FATAL}};
auto levelIt = levelMap.find(envLogLevel);
return levelIt != levelMap.end() ? levelIt->second : LogLevel::ERROR;
}
LogCoreSip::LogCoreSip()
{
bool isModuleSet = false;
auto moduleLevel_ = GetModuleLogLevelFromEnv(isModuleSet);
level_ = isModuleSet ? moduleLevel_ : GetLogLevelFromEnv();
if (strcmp(LogLevelToString(level_).c_str(), "FATAL") == 0) {
return;
}
if (GetLogToStdoutFromEnv()) {
AddSink(std::make_shared<LogSinkStdoutSip>());
} else if (!GetLogToStdoutFromEnv() && GetLogToFileFromEnv()) {
AddSink(std::make_shared<AsdSip::LogSinkFileSip>());
}
}
LogCoreSip &LogCoreSip::InstanceSip()
{
static LogCoreSip logCore;
return logCore;
}
LogLevel LogCoreSip::GetLogLevel() const { return level_; }
void LogCoreSip::SetLogLevel(LogLevel level) { level_ = level; }
void LogCoreSip::LogSip(const char *log, uint64_t logLen)
{
for (auto &sink : sinks_) {
sink->LogSip(log, logLen);
}
}
void LogCoreSip::DeleteLogFileSink()
{
if (sinks_.size() == 0) {
ASDSIP_LOG(ERROR) << "sink_ is empty";
return;
}
sinks_.pop_back();
}
void LogCoreSip::AddSink(std::shared_ptr<LogSinkSip> sink)
{
if (sink == nullptr) {
ASDSIP_LOG(ERROR) << "sink is NULL";
return;
}
sinks_.push_back(sink);
}
const std::vector<std::shared_ptr<LogSinkSip>> &LogCoreSip::GetAllSinks() const { return sinks_; }
}