LCOV - code coverage report
Current view: top level - error_manager - error_manager.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 91.6 % 703 644
Test Date: 2026-08-31 10:05:52 Functions: 95.9 % 74 71

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2025 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : 
      11              : #include <fstream>
      12              : #include <iostream>
      13              : #include <mutex>
      14              : #include <nlohmann/json.hpp>
      15              : #include <sstream>
      16              : #include <exception>
      17              : #include <securec.h>
      18              : #include "mmpa/mmpa_api.h"
      19              : #include "dlog_pub.h"
      20              : #include "base/err_msg.h"
      21              : #include "base/err_mgr.h"
      22              : #include "error_manager.h"
      23              : 
      24              : #define GE_MODULE_NAME static_cast<int32_t>(GE)
      25              : 
      26              : template <typename TI, typename TO>
      27           97 : inline TO* PtrToPtr(TI* const ptr)
      28              : {
      29           97 :     return reinterpret_cast<TO*>(ptr);
      30              : }
      31              : 
      32              : template <typename TI, typename TO>
      33          377 : inline const TO* PtrToPtr(const TI* const ptr)
      34              : {
      35          377 :     return reinterpret_cast<const TO*>(ptr);
      36              : }
      37              : 
      38              : namespace {
      39              : const std::string kParamCheckErrorSuffix = "8888";
      40              : class GeLog {
      41              : public:
      42           26 :     static uint64_t GetTid()
      43              :     {
      44              : #ifdef __GNUC__
      45           26 :         thread_local static const uint64_t tid = static_cast<uint64_t>(syscall(__NR_gettid));
      46              : #else
      47              :         thread_local static const uint64_t tid = static_cast<uint64_t>(GetCurrentThreadId());
      48              : #endif
      49           26 :         return tid;
      50              :     }
      51              : };
      52              : 
      53        28452 : inline bool IsLogEnable(const int32_t module_name, const int32_t log_level)
      54              : {
      55        28452 :     const int32_t enable = CheckLogLevel(module_name, log_level);
      56              :     // 1:enable, 0:disable
      57        28452 :     return (enable == 1);
      58              : }
      59              : 
      60          391 : std::string CurrentTimeFormatStr()
      61              : {
      62          391 :     std::string time_str;
      63          391 :     auto now = std::chrono::system_clock::now();
      64          391 :     auto milli_seconds = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
      65          391 :     auto micro_seconds = std::chrono::time_point_cast<std::chrono::microseconds>(now);
      66          391 :     const auto now_t = std::chrono::system_clock::to_time_t(now);
      67          391 :     const std::tm* tm_now = std::localtime(&now_t);
      68          391 :     if (tm_now == nullptr) {
      69            0 :         return time_str;
      70              :     }
      71              : 
      72          391 :     constexpr int32_t year_base = 1900;
      73          391 :     constexpr size_t kMaxTimeLen = 128U;
      74          391 :     constexpr int64_t kOneThousandMs = 1000L;
      75          391 :     error_message::char_t format_time[kMaxTimeLen] = {};
      76          782 :     (void)snprintf_s(
      77              :         format_time, kMaxTimeLen, kMaxTimeLen - 1U, "%04d-%02d-%02d-%02d:%02d:%02d.%03ld.%03ld",
      78          391 :         tm_now->tm_year + year_base, tm_now->tm_mon + 1, tm_now->tm_mday, tm_now->tm_hour, tm_now->tm_min,
      79          391 :         tm_now->tm_sec, milli_seconds.time_since_epoch().count() % kOneThousandMs,
      80          391 :         micro_seconds.time_since_epoch().count() % kOneThousandMs);
      81          391 :     time_str = format_time;
      82          391 :     return time_str;
      83            0 : }
      84              : } // namespace
      85              : 
      86              : #define GELOGE(fmt, ...)                                                                 \
      87              :     do {                                                                                 \
      88              :         dlog_error(                                                                      \
      89              :             GE_MODULE_NAME, "%" PRIu64 " %s: %s" fmt, GeLog::GetTid(), &__FUNCTION__[0], \
      90              :             ErrorManager::GetInstance().GetLogHeader().c_str(), ##__VA_ARGS__);          \
      91              :     } while (false)
      92              : 
      93              : #define GELOGW(fmt, ...)                                                                                        \
      94              :     do {                                                                                                        \
      95              :         if (IsLogEnable(GE_MODULE_NAME, DLOG_WARN)) {                                                           \
      96              :             dlog_warn(GE_MODULE_NAME, "%" PRIu64 " %s:" fmt, GeLog::GetTid(), &__FUNCTION__[0], ##__VA_ARGS__); \
      97              :         }                                                                                                       \
      98              :     } while (false)
      99              : 
     100              : #define GELOGI(fmt, ...)                                                                                        \
     101              :     do {                                                                                                        \
     102              :         if (IsLogEnable(GE_MODULE_NAME, DLOG_INFO)) {                                                           \
     103              :             dlog_info(GE_MODULE_NAME, "%" PRIu64 " %s:" fmt, GeLog::GetTid(), &__FUNCTION__[0], ##__VA_ARGS__); \
     104              :         }                                                                                                       \
     105              :     } while (false)
     106              : 
     107              : #define GELOGD(fmt, ...)                                                                                         \
     108              :     do {                                                                                                         \
     109              :         if (IsLogEnable(GE_MODULE_NAME, DLOG_DEBUG)) {                                                           \
     110              :             dlog_debug(GE_MODULE_NAME, "%" PRIu64 " %s:" fmt, GeLog::GetTid(), &__FUNCTION__[0], ##__VA_ARGS__); \
     111              :         }                                                                                                        \
     112              :     } while (false)
     113              : 
     114              : namespace {
     115            8 : int32_t ReportInnerErrorMessage(
     116              :     const char* file_name, const char* func, uint32_t line, const char* error_code, const char* format,
     117              :     va_list arg_list)
     118              : {
     119            8 :     std::vector<char> buf(LIMIT_PER_MESSAGE, '\0');
     120            8 :     auto ret = vsprintf_s(buf.data(), LIMIT_PER_MESSAGE, format, arg_list);
     121            8 :     if (ret < 0) {
     122            3 :         GELOGE("[Check][Param] FormatErrorMessage failed, ret:%d, file:%s, line:%u", ret, file_name, line);
     123            3 :         return -1;
     124              :     }
     125            5 :     ret = sprintf_s(
     126            5 :         buf.data() + ret, LIMIT_PER_MESSAGE - static_cast<size_t>(ret), "[FUNC:%s][FILE:%s][LINE:%u]", func,
     127           10 :         error_message::TrimPath(std::string(file_name)).c_str(), line);
     128            5 :     if (ret < 0) {
     129            1 :         GELOGE("[Check][Param] FormatErrorMessage failed, ret:%d, file:%s, line:%u", ret, file_name, line);
     130            1 :         return -1;
     131              :     }
     132              : 
     133           20 :     return ErrorManager::GetInstance().ReportInterErrMessage(error_code, std::string(buf.data()));
     134            8 : }
     135              : 
     136           44 : std::unique_ptr<error_message::char_t[]> CreateUniquePtrFromString(const std::string& str)
     137              : {
     138           44 :     const size_t buf_size = str.empty() ? 1U : (str.size() + 1U);
     139           44 :     auto uni_ptr = std::make_unique<error_message::char_t[]>(buf_size);
     140           44 :     if (uni_ptr == nullptr) {
     141            0 :         return nullptr;
     142              :     }
     143              : 
     144           44 :     if (str.empty()) {
     145           11 :         uni_ptr[0U] = '\0';
     146              :     } else {
     147              :         // 当src size < dst size时,strncpy_s会在末尾str.size()位置添加'\0'
     148           33 :         if (strncpy_s(uni_ptr.get(), str.size() + 1, str.c_str(), str.size()) != EOK) {
     149            0 :             return nullptr;
     150              :         }
     151              :     }
     152           44 :     return uni_ptr;
     153           44 : }
     154              : 
     155           66 : void ClearMessageContainerByWorkId(
     156              :     std::map<uint64_t, std::vector<ErrorManager::ErrorItem>>& message_container, const uint64_t work_stream_id)
     157              : {
     158              :     const std::map<uint64_t, std::vector<ErrorManager::ErrorItem>>::const_iterator err_iter =
     159           66 :         message_container.find(work_stream_id);
     160           66 :     if (err_iter != message_container.cend()) {
     161           45 :         (void)message_container.erase(err_iter);
     162              :     }
     163           66 : }
     164              : 
     165          739 : std::vector<ErrorManager::ErrorItem>& GetOrCreateMessageContainerByWorkId(
     166              :     std::map<uint64_t, std::vector<ErrorManager::ErrorItem>>& message_container, uint64_t work_id)
     167              : {
     168          739 :     auto iter = message_container.find(work_id);
     169          739 :     if (iter == message_container.end()) {
     170           62 :         (void)message_container.emplace(work_id, std::vector<ErrorManager::ErrorItem>());
     171           62 :         iter = message_container.find(work_id);
     172              :     }
     173         1478 :     return iter->second;
     174              : }
     175              : } // namespace
     176              : 
     177              : namespace error_message {
     178              : // first stage
     179              : const std::string kInitialize = "INIT";
     180              : const std::string kModelCompile = "COMP";
     181              : const std::string kModelLoad = "LOAD";
     182              : const std::string kModelExecute = "EXEC";
     183              : const std::string kFinalize = "FINAL";
     184              : 
     185              : // SecondStage
     186              : // INITIALIZE
     187              : const std::string kParser = "PARSER";
     188              : const std::string kOpsProtoInit = "OPS_PRO";
     189              : const std::string kSystemInit = "SYS";
     190              : const std::string kEngineInit = "ENGINE";
     191              : const std::string kOpsKernelInit = "OPS_KER";
     192              : const std::string kOpsKernelBuilderInit = "OPS_KER_BLD";
     193              : // MODEL_COMPILE
     194              : const std::string kPrepareOptimize = "PRE_OPT";
     195              : const std::string kOriginOptimize = "ORI_OPT";
     196              : const std::string kSubGraphOptimize = "SUB_OPT";
     197              : const std::string kMergeGraphOptimize = "MERGE_OPT";
     198              : const std::string kPreBuild = "PRE_BLD";
     199              : const std::string kStreamAlloc = "STM_ALLOC";
     200              : const std::string kMemoryAlloc = "MEM_ALLOC";
     201              : const std::string kTaskGenerate = "TASK_GEN";
     202              : // COMMON
     203              : const std::string kOther = "DEFAULT";
     204              : 
     205              : #ifdef __GNUC__
     206            6 : std::string TrimPath(const std::string& str)
     207              : {
     208            6 :     if (str.find_last_of('/') != std::string::npos) {
     209            0 :         return str.substr(str.find_last_of('/') + 1U);
     210              :     }
     211            6 :     return str;
     212              : }
     213              : #else
     214              : std::string TrimPath(const std::string& str)
     215              : {
     216              :     if (str.find_last_of('\\') != std::string::npos) {
     217              :         return str.substr(str.find_last_of('\\') + 1U);
     218              :     }
     219              :     return str;
     220              : }
     221              : #endif
     222              : 
     223            1 : int32_t FormatErrorMessage(char_t* str_dst, size_t dst_max, const char_t* format, ...)
     224              : {
     225              :     int32_t ret;
     226              :     va_list arg_list;
     227              : 
     228            1 :     va_start(arg_list, format);
     229            1 :     ret = vsprintf_s(str_dst, dst_max, format, arg_list);
     230              :     (void)arg_list;
     231            1 :     va_end(arg_list);
     232            1 :     if (ret < 0) {
     233            0 :         GELOGE("[Check][Param] FormatErrorMessage failed, ret:%d, pattern:%s", ret, format);
     234              :     }
     235            1 :     return ret;
     236              : }
     237              : 
     238            0 : void ReportInnerError(
     239              :     const char_t* file_name, const char_t* func, uint32_t line, const std::string error_code, const char_t* format, ...)
     240              : {
     241              :     va_list arg_list;
     242            0 :     va_start(arg_list, format);
     243            0 :     (void)ReportInnerErrorMessage(file_name, func, line, error_code.c_str(), format, arg_list);
     244            0 :     va_end(arg_list);
     245            0 :     return;
     246              : }
     247              : } // namespace error_message
     248              : 
     249              : namespace {
     250              : #ifdef __GNUC__
     251              : constexpr const error_message::char_t* const kErrorCodePath = "../conf/error_manager/error_code.json";
     252              : constexpr const error_message::char_t* const kSeparator = "/";
     253              : #else
     254              : const error_message::char_t* const kErrorCodePath = "..\\conf\\error_manager\\error_code.json";
     255              : const error_message::char_t* const kSeparator = "\\";
     256              : #endif
     257              : 
     258              : constexpr uint64_t kLength = 2UL;
     259              : 
     260        60645 : void Ltrim(std::string& s)
     261              : {
     262        60645 :     (void)s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](const error_message::char_t c) -> bool {
     263        71206 :                       return static_cast<bool>(std::isspace(static_cast<uint8_t>(c)) == 0);
     264              :                   }));
     265        60645 : }
     266              : 
     267        60645 : void Rtrim(std::string& s)
     268              : {
     269       121290 :     (void)s.erase(
     270        60645 :         std::find_if(
     271        60645 :             s.rbegin(), s.rend(),
     272        60711 :             [](const error_message::char_t c) -> bool {
     273        60711 :                 return static_cast<bool>(std::isspace(static_cast<uint8_t>(c)) == 0);
     274              :             })
     275              :             .base(),
     276              :         s.end());
     277        60645 : }
     278              : 
     279              : /// @ingroup domi_common
     280              : /// @brief trim space
     281        60645 : void Trim(std::string& s)
     282              : {
     283        60645 :     Rtrim(s);
     284        60645 :     Ltrim(s);
     285        60645 : }
     286              : 
     287              : /// @brief Obtain error manager self library path
     288              : /// @return store liberror_manager.so path
     289           21 : std::string GetSelfLibraryDir(void)
     290              : {
     291           21 :     mmDlInfo dl_info{nullptr, nullptr, nullptr, nullptr, 0, 0, 0};
     292           21 :     if (mmDladdr(reinterpret_cast<void*>(GetSelfLibraryDir), &dl_info) != EN_OK) {
     293            0 :         const error_message::char_t* error = mmDlerror();
     294            0 :         error = (error == nullptr) ? "" : error;
     295            0 :         GELOGW("Failed to read the shared library file path! reason:%s", error);
     296            0 :         return std::string();
     297              :     } else {
     298           21 :         std::string so_path = dl_info.dli_fname;
     299           21 :         error_message::char_t path[MMPA_MAX_PATH] = {};
     300           21 :         if (so_path.length() >= static_cast<size_t>(MMPA_MAX_PATH)) {
     301            0 :             GELOGW("The shared library file path is too long!");
     302            0 :             return std::string();
     303              :         }
     304           21 :         if (mmRealPath(so_path.c_str(), &(path[0]), MMPA_MAX_PATH) != EN_OK) {
     305            0 :             GELOGW("Failed to get realpath of %s, reason:%s", so_path.c_str(), strerror(errno));
     306            0 :             return std::string();
     307              :         }
     308              : 
     309           21 :         so_path = &(path[0]);
     310           21 :         so_path = so_path.substr(0U, so_path.rfind(kSeparator) + 1U);
     311           21 :         return so_path;
     312           21 :     }
     313              : }
     314              : 
     315              : // split string
     316        27106 : std::vector<std::string> SplitByDelim(const std::string& str, const error_message::char_t delim)
     317              : {
     318        27106 :     std::vector<std::string> elems;
     319              : 
     320        27106 :     if (str.empty()) {
     321         3366 :         elems.emplace_back("");
     322         3366 :         return elems;
     323              :     }
     324              : 
     325        23740 :     std::stringstream ss(str);
     326        23740 :     std::string item;
     327              : 
     328        84385 :     while (getline(ss, item, delim)) {
     329        60645 :         Trim(item);
     330        60645 :         elems.push_back(item);
     331              :     }
     332        23740 :     const auto str_size = str.size();
     333        23740 :     if ((str_size > 0U) && (str[str_size - 1U] == delim)) {
     334            0 :         elems.emplace_back("");
     335              :     }
     336              : 
     337        23740 :     return elems;
     338        23740 : }
     339              : } // namespace
     340              : 
     341              : thread_local error_message::Context ErrorManager::error_context_ = {0UL, "", "", ""};
     342              : 
     343              : /// @brief Obtain ErrorManager instance
     344              : /// @return ErrorManager instance
     345          835 : ErrorManager& ErrorManager::GetInstance()
     346              : {
     347          835 :     static ErrorManager instance;
     348          835 :     return instance;
     349              : }
     350              : 
     351              : /// @brief init
     352              : /// @param [in] path: current so path
     353              : /// @return int 0(success) -1(fail)
     354           23 : int32_t ErrorManager::Init(const std::string path)
     355              : {
     356           23 :     const std::string file_path = path + kErrorCodePath;
     357           23 :     GELOGI("Begin to init, path is %s", path.c_str());
     358              :     // error_map_由ParseJsonFormatString内部持mutex_保护, 此处不再持锁:
     359              :     // 一方面避免文件IO在临界区内执行, 另一方面避免与ParseJsonFormatString的加锁递归
     360           23 :     const int32_t ret = ParseJsonFile(file_path);
     361           23 :     if (ret != 0) {
     362           23 :         GELOGW("[Parse][File]Parse config file:%s failed", file_path.c_str());
     363           23 :         return -1;
     364              :     }
     365            0 :     is_init_.store(true, std::memory_order_release);
     366            0 :     return 0;
     367           23 : }
     368              : 
     369              : /// @brief init
     370              : /// @return int 0(success) -1(fail)
     371            1 : int32_t ErrorManager::Init() { return Init(GetSelfLibraryDir()); }
     372              : 
     373          409 : int32_t ErrorManager::EnsureInitialized()
     374              : {
     375          409 :     if (is_init_.load(std::memory_order_acquire)) {
     376          391 :         return 0;
     377              :     }
     378           18 :     const std::unique_lock<std::mutex> lck(init_mutex_);
     379           18 :     if (is_init_.load(std::memory_order_relaxed)) {
     380            0 :         return 0;
     381              :     }
     382           18 :     return Init(GetSelfLibraryDir());
     383           18 : }
     384              : 
     385            5 : int32_t ErrorManager::Init(error_message::ErrorMsgMode error_mode)
     386              : {
     387            5 :     if (error_mode >= error_message::ErrorMsgMode::ERR_MSG_MODE_MAX) {
     388            3 :         GELOGE("[Init][Error]error mode is invalid %u", error_mode);
     389            3 :         return -1;
     390              :     }
     391            2 :     const int32_t ret = Init(GetSelfLibraryDir());
     392            2 :     if (ret != 0) {
     393            2 :         return -1;
     394              :     }
     395            0 :     error_mode_.store(error_mode, std::memory_order_release);
     396            0 :     return 0;
     397              : }
     398              : 
     399           37 : int32_t ErrorManager::ReportInterErrMessage(const std::string error_code, const std::string& error_msg)
     400              : {
     401           37 :     std::string report_time = CurrentTimeFormatStr();
     402           37 :     constexpr uint64_t kMaxWorkSize = 1000UL;
     403           37 :     if (EnsureInitialized() != 0) {
     404            8 :         GELOGI("ErrorManager has not been initialized, can't report error_message.");
     405            8 :         return -1;
     406              :     }
     407           29 :     if (!IsInnerErrorCode(error_code)) {
     408            2 :         GELOGE("[Report][Error]error_code %s is not internal error code", error_code.c_str());
     409            2 :         return -1;
     410              :     }
     411              : 
     412           27 :     const std::unique_lock<std::mutex> lck(mutex_);
     413           27 :     if (error_context_.work_stream_id == 0UL) {
     414            2 :         if (error_message_per_work_id_.size() > kMaxWorkSize) {
     415            1 :             GELOGW(
     416              :                 "[Report][Error]error_code %s, error work_stream total size exceed %lu, skip record",
     417              :                 error_code.c_str(), kMaxWorkSize);
     418            1 :             return -1;
     419              :         }
     420            1 :         GenWorkStreamIdDefault();
     421              :     }
     422              : 
     423           26 :     GELOGI(
     424              :         "report error_message, error_code:%s, work_stream_id:%lu, error_mode:%u", error_code.c_str(),
     425              :         error_context_.work_stream_id, static_cast<uint32_t>(error_mode_.load(std::memory_order_relaxed)));
     426              : 
     427           26 :     auto& error_messages = GetErrorMsgContainer(error_context_.work_stream_id);
     428           26 :     auto& warning_messages = GetWarningMsgContainer(error_context_.work_stream_id);
     429              : 
     430           26 :     if (error_messages.size() > kMaxWorkSize) {
     431            1 :         GELOGW(
     432              :             "[Report][Error]error_code %s, error work_stream_id:%lu item size exceed %lu, skip record",
     433              :             error_code.c_str(), error_context_.work_stream_id, kMaxWorkSize);
     434            1 :         return -1;
     435              :     }
     436              : 
     437           25 :     std::string tmp = error_msg;
     438           25 :     if (error_mode_.load(std::memory_order_acquire) == error_message::ErrorMsgMode::PROCESS_MODE) {
     439            8 :         tmp += "[THREAD:" + std::to_string(mmGetTid()) + "]";
     440              :     }
     441              : 
     442          175 :     ErrorManager::ErrorItem item = {error_code, "", tmp, "", "", {}, report_time};
     443           25 :     if (error_code[0UL] == 'W') {
     444           10 :         const auto it = find(warning_messages.begin(), warning_messages.end(), item);
     445           20 :         if (it == warning_messages.end()) {
     446           10 :             warning_messages.emplace_back(item);
     447              :         }
     448              :     } else {
     449           15 :         const auto it = find(error_messages.begin(), error_messages.end(), item);
     450           30 :         if (it == error_messages.end()) {
     451           15 :             error_messages.emplace_back(item);
     452              :         }
     453              :     }
     454           25 :     return 0;
     455           37 : }
     456              : 
     457              : /// @brief report error message
     458              : /// @param [in] error_code: error code
     459              : /// @param [in] args_map: parameter map
     460              : /// @return int 0(success) -1(fail)
     461          346 : int32_t ErrorManager::ReportErrMessage(const std::string error_code, const std::map<std::string, std::string>& args_map)
     462              : {
     463          346 :     std::string report_time = CurrentTimeFormatStr();
     464          346 :     if (EnsureInitialized() != 0) {
     465            8 :         GELOGI("ErrorManager has not been initialized, can't report error_message.");
     466            8 :         return 0;
     467              :     }
     468              : 
     469          338 :     if (error_context_.work_stream_id == 0UL) {
     470           11 :         GenWorkStreamIdDefault();
     471              :     }
     472              : 
     473          338 :     GELOGI(
     474              :         "report error_message, error_code:%s, work_stream_id:%lu, error_mode:%u.", error_code.c_str(),
     475              :         error_context_.work_stream_id, static_cast<uint32_t>(error_mode_.load(std::memory_order_relaxed)));
     476              :     // error_map_可能被ParseJsonFormatString并发改写, 此处必须持锁查找并整体拷贝出配置,
     477              :     // 不能在锁外继续持有指向map内部的引用
     478          338 :     ErrorInfoConfig error_info;
     479              :     {
     480          338 :         const std::unique_lock<std::mutex> lock(mutex_);
     481          338 :         const std::map<std::string, ErrorManager::ErrorInfoConfig>::const_iterator iter = error_map_.find(error_code);
     482          338 :         if (iter == error_map_.cend()) {
     483            2 :             GELOGW("[Report][Warning]error_code %s is not registered", error_code.c_str());
     484            2 :             return -1;
     485              :         }
     486          336 :         error_info = iter->second;
     487          338 :     }
     488          336 :     std::string error_message = error_info.error_message;
     489         1010 :     for (const std::string& arg : error_info.arg_list) {
     490          345 :         if (arg.empty()) {
     491            4 :             GELOGI("arg is null");
     492            4 :             break;
     493              :         }
     494          341 :         const auto arg_it = args_map.find(arg);
     495          341 :         if (arg_it == args_map.end()) {
     496            2 :             GELOGE("[Report][Error]error_code: %s, arg %s does not exist in map", error_code.c_str(), arg.c_str());
     497            3 :             return -1;
     498              :         }
     499          339 :         const std::string& arg_value = arg_it->second;
     500          339 :         const auto index = error_message.find("%s");
     501          339 :         if (index == std::string::npos) {
     502            1 :             GELOGE(
     503              :                 "[Report][Error]error_code: %s, %s location in error_message is not found", error_code.c_str(),
     504              :                 arg.c_str());
     505            1 :             return -1;
     506              :         }
     507          338 :         (void)error_message.replace(index, kLength, arg_value);
     508              :     }
     509              : 
     510          333 :     const std::unique_lock<std::mutex> lock(mutex_);
     511          333 :     auto& error_messages = GetErrorMsgContainer(error_context_.work_stream_id);
     512          333 :     auto& warning_messages = GetWarningMsgContainer(error_context_.work_stream_id);
     513              : 
     514          333 :     if (error_mode_.load(std::memory_order_acquire) == error_message::ErrorMsgMode::PROCESS_MODE) {
     515            8 :         error_message += "[THREAD:" + std::to_string(mmGetTid()) + "]";
     516              :     }
     517              :     ErrorManager::ErrorItem error_item = {
     518              :         error_code, error_info.error_title, error_message, error_info.possible_cause, error_info.solution, args_map,
     519          333 :         report_time};
     520          333 :     if (error_code[0UL] == 'W') {
     521           11 :         const auto it = find(warning_messages.begin(), warning_messages.end(), error_item);
     522           22 :         if (it == warning_messages.end()) {
     523           11 :             warning_messages.emplace_back(error_item);
     524              :         }
     525              :     } else {
     526          322 :         const auto it = find(error_messages.begin(), error_messages.end(), error_item);
     527          644 :         if (it == error_messages.end()) {
     528           19 :             error_messages.emplace_back(error_item);
     529              :         }
     530              :     }
     531          333 :     return 0;
     532          346 : }
     533              : 
     534            8 : int32_t ErrorManager::ReportErrMsgWithoutTpl(const std::string& error_code, const std::string& errmsg)
     535              : {
     536            8 :     std::string report_time = CurrentTimeFormatStr();
     537            8 :     if (EnsureInitialized() != 0) {
     538            1 :         GELOGI("ErrorManager has not been initialized, can't report error_message.");
     539            1 :         return -1;
     540              :     }
     541              : 
     542            7 :     if (error_context_.work_stream_id == 0UL) {
     543            1 :         GenWorkStreamIdDefault();
     544              :     }
     545              : 
     546            7 :     auto final_error_code = error_code;
     547            7 :     if (!IsUserDefinedErrorCode(final_error_code)) {
     548            5 :         GELOGW(
     549              :             "[Report] Current error code is [%s], suggest using the recommended U segment. "
     550              :             "The error code EU0000 is reported!",
     551              :             final_error_code.c_str());
     552            5 :         final_error_code = "EU0000";
     553              :     }
     554              : 
     555            7 :     GELOGI(
     556              :         "report error_message, error_code:%s, work_stream_id:%lu, error_mode:%u.", error_code.c_str(),
     557              :         error_context_.work_stream_id, static_cast<uint32_t>(error_mode_.load(std::memory_order_relaxed)));
     558              : 
     559            7 :     const std::unique_lock<std::mutex> lock(mutex_);
     560            7 :     auto& error_messages = GetErrorMsgContainer(error_context_.work_stream_id);
     561              : 
     562           49 :     ErrorItem error_item{final_error_code, "", errmsg, "", "", {}, report_time};
     563            7 :     const auto it = find(error_messages.begin(), error_messages.end(), error_item);
     564           14 :     if (it == error_messages.end()) {
     565            7 :         error_messages.emplace_back(error_item);
     566              :     }
     567            7 :     return 0;
     568            8 : }
     569              : 
     570            4 : void ErrorManager::AssembleInnerErrorMessage(
     571              :     const std::vector<ErrorItem>& error_messages, const std::string& first_code, std::stringstream& err_stream) const
     572              : {
     573            4 :     std::string current_code_print = first_code;
     574            4 :     const bool IsErrorId = IsParamCheckErrorId(first_code);
     575           12 :     for (auto& item : error_messages) {
     576            6 :         if (!IsParamCheckErrorId(item.error_id)) {
     577            2 :             current_code_print = item.error_id;
     578            2 :             break;
     579              :         }
     580              :     }
     581            4 :     err_stream << current_code_print << ": Internal error!" << std::endl;
     582            4 :     bool print_traceback_once = false;
     583           14 :     for (auto& item : error_messages) { // Display the first non 8888 error code
     584            6 :         if (IsParamCheckErrorId(item.error_id) && IsErrorId) {
     585            4 :             err_stream << "        " << item.error_message << std::endl;
     586            4 :             continue;
     587              :         }
     588            2 :         current_code_print == "      " ?
     589            0 :             (err_stream << current_code_print << " " << item.error_message << std::endl) :
     590            4 :             (err_stream << current_code_print << "[PID: " << std::to_string(mmGetPid()) << "] " << item.report_time
     591            4 :                         << " " << item.error_title << "(" << item.error_id << "): "
     592            4 :                         << " " << item.error_message << std::endl);
     593              : 
     594            2 :         current_code_print = "      ";
     595            2 :         if (!print_traceback_once) {
     596            2 :             err_stream << "TraceBack (most recent call last):" << std::endl;
     597            2 :             print_traceback_once = true;
     598              :         }
     599              :     }
     600            4 : }
     601              : 
     602           36 : std::string ErrorManager::GetErrorMessage()
     603              : {
     604           36 :     const auto& error_messages = GetRawErrorMessages();
     605           36 :     if (error_messages.empty()) {
     606           30 :         return "";
     607              :     }
     608              : 
     609           21 :     std::stringstream err_stream;
     610           21 :     std::string first_code = error_messages[0UL].error_id;
     611           48 :     for (const auto& item : error_messages) {
     612           23 :         if (!IsInnerErrorCode(item.error_id)) {
     613           17 :             first_code = item.error_id;
     614           34 :             err_stream << "[PID: " << std::to_string(mmGetPid()) << "] " << item.report_time << " " << item.error_title
     615           34 :                        << "(" << first_code << "): " << item.error_message << std::endl;
     616           17 :             if (!item.possible_cause.empty() && item.possible_cause != "N/A") {
     617            1 :                 err_stream << "        Possible Cause: " << item.possible_cause << std::endl;
     618              :             }
     619           17 :             if (!item.solution.empty() && item.solution != "N/A") {
     620            5 :                 err_stream << "        Solution: " << item.solution << std::endl;
     621              :             }
     622           17 :             break;
     623              :         }
     624              :     }
     625           21 :     if (IsInnerErrorCode(first_code)) {
     626            4 :         AssembleInnerErrorMessage(error_messages, first_code, err_stream);
     627              :     } else {
     628           17 :         bool print_traceback_once = false;
     629           66 :         for (const auto& item : error_messages) {
     630           32 :             if (first_code == item.error_id && error_messages[0].error_message == item.error_message) {
     631           18 :                 continue;
     632              :             }
     633           14 :             if (!print_traceback_once) {
     634            6 :                 err_stream << "TraceBack (most recent call last):" << std::endl;
     635            6 :                 print_traceback_once = true;
     636              :             }
     637           14 :             err_stream << "        " << item.error_message << std::endl;
     638              :         }
     639              :     }
     640           21 :     const std::unique_lock<std::mutex> lck(mutex_);
     641           21 :     ClearErrorMsgContainer(error_context_.work_stream_id);
     642           21 :     return err_stream.str();
     643           36 : }
     644              : 
     645           15 : std::string ErrorManager::GetWarningMessage()
     646              : {
     647           15 :     GELOGI(
     648              :         "current work_stream_id:%lu, error_mode:%u", error_context_.work_stream_id,
     649              :         static_cast<uint32_t>(error_mode_.load(std::memory_order_relaxed)));
     650           15 :     const std::unique_lock<std::mutex> lck(mutex_);
     651           15 :     auto& warning_messages = GetWarningMsgContainer(error_context_.work_stream_id);
     652              : 
     653           15 :     std::stringstream warning_stream;
     654           45 :     for (auto& item : warning_messages) {
     655           30 :         warning_stream << "[PID: " << std::to_string(mmGetPid()) << "] " << item.report_time << " " << item.error_title
     656           30 :                        << "(" << item.error_id << "): " << item.error_message << std::endl;
     657              :     }
     658           15 :     ClearWarningMsgContainer(error_context_.work_stream_id);
     659           30 :     return warning_stream.str();
     660           15 : }
     661              : 
     662              : /// @brief output error message
     663              : /// @param [in] handle: print handle
     664              : /// @return int 0(success) -1(fail)
     665            2 : int32_t ErrorManager::OutputErrMessage(int32_t handle)
     666              : {
     667            2 :     std::string err_msg = GetErrorMessage();
     668            2 :     if (err_msg.empty()) {
     669            2 :         std::stringstream err_stream;
     670            2 :         err_stream << "E19999: Internal error!" << std::endl;
     671              :         err_stream << "        "
     672            2 :                    << "Unknown error occurred. Please check the log." << std::endl;
     673            2 :         err_msg = err_stream.str();
     674            2 :     }
     675              : 
     676            2 :     if (handle <= fileno(stderr)) {
     677            1 :         std::cout << err_msg << std::endl;
     678              :     } else {
     679            1 :         const mmSsize_t ret = mmWrite(
     680            1 :             handle, const_cast<error_message::char_t*>(err_msg.c_str()), static_cast<uint32_t>(err_msg.length()));
     681            1 :         if (ret == -1) {
     682            1 :             GELOGE("[Write][File]fail, reason:%s", strerror(errno));
     683            1 :             return -1;
     684              :         }
     685              :     }
     686            1 :     return 0;
     687            2 : }
     688              : 
     689              : /// @brief output message
     690              : /// @param [in] handle: print handle
     691              : /// @return int 0(success) -1(fail)
     692            1 : int32_t ErrorManager::OutputMessage(int32_t handle)
     693              : {
     694            1 :     const std::string warning_msg = GetWarningMessage();
     695            1 :     std::cout << warning_msg << std::endl;
     696            1 :     handle = 0;
     697            1 :     return handle;
     698            1 : }
     699              : 
     700           24 : int32_t ErrorManager::ParseJsonFile(const std::string path)
     701              : {
     702           24 :     GELOGD("Begin to parse json file, path is %s", path.c_str());
     703           24 :     nlohmann::json json_file;
     704           24 :     const int32_t status = ReadJsonFile(path, &json_file);
     705           24 :     if (status != 0) {
     706           23 :         GELOGW("[Read][JsonFile]file path is %s", path.c_str());
     707           23 :         return -1;
     708              :     }
     709            1 :     return ParseJsonFormatString(PtrToPtr<nlohmann::json, void>(&json_file));
     710           24 : }
     711              : /// @brief parse json file
     712              : /// @param [in] handle: json handle
     713              : /// @return int 0(success) -1(fail)
     714          377 : int32_t ErrorManager::ParseJsonFormatString(const void* const handle, uint32_t priority)
     715              : {
     716          377 :     GELOGD("Begin to parse json string");
     717              :     // 本接口是公开接口, RegisterFormatErrorMessage会在运行期由任意线程调用, 必须持锁改写error_map_
     718          377 :     const std::unique_lock<std::mutex> lck(mutex_);
     719              :     try {
     720          377 :         const nlohmann::json* const json_file = PtrToPtr<void, nlohmann::json>(handle);
     721          377 :         if (json_file->find("error_info_list") == json_file->end()) {
     722            2 :             GELOGW("[Check][Config]The message of error_info_list is not found");
     723            2 :             return -1;
     724              :         }
     725          375 :         const nlohmann::json& error_list_json = json_file->at("error_info_list");
     726          375 :         if (error_list_json.is_null() || !error_list_json.is_array()) {
     727            1 :             GELOGW("[Check][Config]The message of error_info_list is not found or "
     728              :                    "the message of error_info_list is not array");
     729            1 :             return -1;
     730              :         }
     731        27480 :         for (const auto& error_json : error_list_json) {
     732        27107 :             ErrorInfoConfig error_info;
     733        27107 :             error_info.error_id = error_json["ErrCode"];
     734        27106 :             error_info.error_message = error_json["ErrMessage"];
     735        27106 :             if (error_json.contains("errTitle")) {
     736        24032 :                 error_info.error_title = error_json["errTitle"];
     737              :             }
     738        27106 :             if (error_json.contains("suggestion")) {
     739        11162 :                 error_info.possible_cause = error_json["suggestion"]["Possible Cause"];
     740        11162 :                 error_info.solution = error_json["suggestion"]["Solution"];
     741              :             }
     742        27106 :             error_info.arg_list = SplitByDelim(error_json["Arglist"], ',');
     743        27106 :             error_info.priority = priority;
     744        27106 :             auto it = error_map_.find(error_info.error_id);
     745        27106 :             if (it == error_map_.cend()) {
     746          715 :                 (void)error_map_.emplace(error_info.error_id, error_info);
     747          715 :                 GELOGD("add error_code %s success", error_info.error_id.c_str());
     748              :             } else {
     749        26391 :                 if (it->second.priority < error_info.priority) {
     750            0 :                     it->second = error_info;
     751            0 :                     GELOGD(
     752              :                         "Update error_code %s success, current priority[%u] is greater than saved priority[%u]",
     753              :                         error_info.error_id.c_str(), priority, it->second.priority);
     754              :                 } else {
     755        26391 :                     GELOGD(
     756              :                         "No need update error_code %s, due to current priority[%u] is less than "
     757              :                         "or equal to saved priority[%u]",
     758              :                         error_info.error_id.c_str(), priority, it->second.priority);
     759              :                 }
     760              :             }
     761        27107 :         }
     762            1 :     } catch (const nlohmann::json::exception& e) {
     763            1 :         GELOGW("[Parse][JsonFile]exception message: %s", e.what());
     764            1 :         return -1;
     765            1 :     }
     766          373 :     return 0;
     767          377 : }
     768              : 
     769              : /// @brief read json file
     770              : /// @param [in] file_path: json path
     771              : /// @param [in] handle:  print handle
     772              : /// @return int 0(success) -1(fail)
     773           98 : int32_t ErrorManager::ReadJsonFile(const std::string& file_path, void* const handle)
     774              : {
     775           98 :     if (file_path.empty()) {
     776            1 :         GELOGW("[Read][JsonFile]path %s is not valid", file_path.c_str());
     777            1 :         return -1;
     778              :     }
     779           97 :     nlohmann::json* const json_file = PtrToPtr<void, nlohmann::json>(handle);
     780           97 :     if (json_file == nullptr) {
     781            1 :         GELOGW("[Check][Param]JsonFile is nullptr");
     782            1 :         return -1;
     783              :     }
     784           96 :     const error_message::char_t* const file = file_path.data();
     785           96 :     if ((mmAccess2(file, M_F_OK)) != EN_OK) {
     786           23 :         GELOGW("[Read][JsonFile] %s does not exist, error %s", file_path.c_str(), strerror(errno));
     787           23 :         return -1;
     788              :     }
     789              : 
     790           73 :     std::ifstream ifs(file_path);
     791           73 :     if (!ifs.is_open()) {
     792            0 :         GELOGW("[Read][JsonFile]Open %s failed", file_path.c_str());
     793            0 :         return -1;
     794              :     }
     795              : 
     796           73 :     const std::string content((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
     797              :     try {
     798           74 :         *json_file = nlohmann::json::parse(content.c_str(), content.c_str() + content.size());
     799            1 :     } catch (const nlohmann::json::exception& e) {
     800            1 :         GELOGW("[Read][JsonFile]Parse json fail. path: %s, exception message: %s.", file_path.c_str(), e.what());
     801            1 :         ifs.close();
     802            1 :         return -1;
     803            1 :     }
     804              : 
     805           72 :     ifs.close();
     806           72 :     GELOGD("Read json file success");
     807           72 :     return 0;
     808           73 : }
     809              : 
     810              : /// @brief report error message
     811              : /// @param [in] error_code: error code
     812              : /// @param [in] vector parameter key, vector parameter value
     813              : /// @return int 0(success) -1(fail)
     814            4 : void ErrorManager::ATCReportErrMessage(
     815              :     const std::string error_code, const std::vector<std::string>& key, const std::vector<std::string>& value)
     816              : {
     817            4 :     if (EnsureInitialized() != 0) {
     818            0 :         GELOGI("ErrorManager has not been initialized, can't report error_message.");
     819            0 :         return;
     820              :     }
     821            4 :     std::map<std::string, std::string> args_map;
     822            4 :     if (key.empty()) {
     823            2 :         (void)ErrorManager::GetInstance().ReportErrMessage(error_code, args_map);
     824            2 :     } else if (key.size() == value.size()) {
     825            2 :         for (size_t i = 0UL; i < key.size(); ++i) {
     826            1 :             (void)args_map.insert(std::make_pair(key[i], value[i]));
     827              :         }
     828            1 :         (void)ErrorManager::GetInstance().ReportErrMessage(error_code, args_map);
     829              :     } else {
     830            1 :         GELOGW("ATCReportErrMessage wrong, vector key and value size is not equal");
     831              :     }
     832            4 : }
     833              : 
     834              : /// @brief report graph compile failed message such as error code and op_name in mustune case
     835              : /// @param [in] msg: failed message map, key is error code, value is op_name
     836              : /// @param [out] classified_msg: classified_msg message map, key is error code, value is op_name vector
     837            4 : void ErrorManager::ClassifyCompileFailedMsg(
     838              :     const std::map<std::string, std::string>& msg, std::map<std::string, std::vector<std::string>>& classified_msg)
     839              : {
     840            8 :     for (const auto& itr : msg) {
     841            4 :         GELOGD("msg is error_code:%s, op_name:%s", itr.first.c_str(), itr.second.c_str());
     842            4 :         const auto err_code_itr = classified_msg.find(itr.first);
     843            4 :         if (err_code_itr == classified_msg.end()) {
     844            9 :             (void)classified_msg.emplace(itr.first, std::vector<std::string>{itr.second});
     845              :         } else {
     846            1 :             std::vector<std::string>& op_name_list = err_code_itr->second;
     847            1 :             op_name_list.emplace_back(itr.second);
     848              :         }
     849              :     }
     850            7 : }
     851              : 
     852              : /// @brief report graph compile failed message such as error code and op_name in mustune case
     853              : /// @param [in] root_graph_name: root graph name
     854              : /// @param [in] msg: failed message map, key is error code, value is op_name
     855              : /// @return int 0(success) -1(fail)
     856            4 : int32_t ErrorManager::ReportMstuneCompileFailedMsg(
     857              :     const std::string& root_graph_name, const std::map<std::string, std::string>& msg)
     858              : {
     859            4 :     if (EnsureInitialized() != 0) {
     860            0 :         GELOGI("ErrorManager has not been initialized, can't report error_message.");
     861            0 :         return 0;
     862              :     }
     863            4 :     if (msg.empty() || root_graph_name.empty()) {
     864            2 :         GELOGW(
     865              :             "Msg or root graph name is empty, msg size is %zu, root graph name is %s", msg.size(),
     866              :             root_graph_name.c_str());
     867            2 :         return -1;
     868              :     }
     869            2 :     GELOGD("Report graph:%s compile failed msg", root_graph_name.c_str());
     870            2 :     const std::unique_lock<std::mutex> lock(mutex_);
     871            2 :     const auto itr = compile_failed_msg_map_.find(root_graph_name);
     872            2 :     if (itr != compile_failed_msg_map_.end()) {
     873            1 :         std::map<std::string, std::vector<std::string>>& classified_msg = itr->second;
     874            1 :         ClassifyCompileFailedMsg(msg, classified_msg);
     875              :     } else {
     876            1 :         std::map<std::string, std::vector<std::string>> classified_msg;
     877            1 :         ClassifyCompileFailedMsg(msg, classified_msg);
     878            1 :         (void)compile_failed_msg_map_.emplace(root_graph_name, classified_msg);
     879            1 :     }
     880            2 :     return 0;
     881            2 : }
     882              : 
     883              : /// @brief get graph compile failed message in mustune case
     884              : /// @param [in] graph_name: graph name
     885              : /// @param [out] msg_map: failed message map, key is error code, value is op_name list
     886              : /// @return int 0(success) -1(fail)
     887            4 : int32_t ErrorManager::GetMstuneCompileFailedMsg(
     888              :     const std::string& graph_name, std::map<std::string, std::vector<std::string>>& msg_map)
     889              : {
     890            4 :     if (EnsureInitialized() != 0) {
     891            0 :         GELOGI("ErrorManager has not been initialized, can't report error_message.");
     892            0 :         return 0;
     893              :     }
     894            4 :     if (!msg_map.empty()) {
     895            2 :         GELOGW("msg_map is not empty, exist msg");
     896            2 :         return -1;
     897              :     }
     898            2 :     const std::unique_lock<std::mutex> lock(mutex_);
     899            2 :     const auto iter = compile_failed_msg_map_.find(graph_name);
     900            2 :     if (iter == compile_failed_msg_map_.end()) {
     901            1 :         GELOGW("can not find graph, name is:%s", graph_name.c_str());
     902            1 :         return -1;
     903              :     } else {
     904            1 :         auto& compile_failed_msg = iter->second;
     905            1 :         msg_map.swap(compile_failed_msg);
     906            1 :         (void)compile_failed_msg_map_.erase(graph_name);
     907              :     }
     908            1 :     GELOGI("get graph:%s compile result msg success", graph_name.c_str());
     909              : 
     910            1 :     return 0;
     911            2 : }
     912              : 
     913          385 : std::vector<ErrorManager::ErrorItem>& ErrorManager::GetErrorMsgContainerByWorkId(uint64_t work_id)
     914              : {
     915          385 :     return GetOrCreateMessageContainerByWorkId(error_message_per_work_id_, work_id);
     916              : }
     917              : 
     918          354 : std::vector<ErrorManager::ErrorItem>& ErrorManager::GetWarningMsgContainerByWorkId(uint64_t work_id)
     919              : {
     920          354 :     return GetOrCreateMessageContainerByWorkId(warning_messages_per_work_id_, work_id);
     921              : }
     922              : 
     923          404 : std::vector<ErrorManager::ErrorItem>& ErrorManager::GetErrorMsgContainer(uint64_t work_stream_id)
     924              : {
     925          404 :     return (error_mode_.load(std::memory_order_acquire) == error_message::ErrorMsgMode::INTERNAL_MODE) ?
     926          384 :                GetErrorMsgContainerByWorkId(work_stream_id) :
     927           20 :                error_message_process_;
     928              : }
     929              : 
     930          374 : std::vector<ErrorManager::ErrorItem>& ErrorManager::GetWarningMsgContainer(uint64_t work_stream_id)
     931              : {
     932          374 :     return (error_mode_.load(std::memory_order_acquire) == error_message::ErrorMsgMode::INTERNAL_MODE) ?
     933          354 :                GetWarningMsgContainerByWorkId(work_stream_id) :
     934           20 :                warning_messages_process_;
     935              : }
     936              : 
     937           15 : void ErrorManager::GenWorkStreamIdDefault()
     938              : {
     939              :     // system getpid and gettid is always successful
     940           15 :     const int32_t pid = mmGetPid();
     941           15 :     const int32_t tid = mmGetTid();
     942              : 
     943           15 :     constexpr uint64_t kPidOffset = 100000UL;
     944           15 :     const uint64_t work_stream_id =
     945           15 :         static_cast<uint64_t>(static_cast<uint32_t>(pid) * kPidOffset) + static_cast<uint64_t>(tid);
     946           15 :     error_context_.work_stream_id = work_stream_id;
     947           15 : }
     948              : 
     949            1 : void ErrorManager::GenWorkStreamIdBySessionGraph(const uint64_t session_id, const uint64_t graph_id)
     950              : {
     951            1 :     constexpr uint64_t kSessionIdOffset = 100000UL;
     952            1 :     const uint64_t work_stream_id = (session_id * kSessionIdOffset) + graph_id;
     953            1 :     error_context_.work_stream_id = work_stream_id;
     954              : 
     955            1 :     const std::unique_lock<std::mutex> lck(mutex_);
     956            1 :     ClearErrorMsgContainerByWorkId(work_stream_id);
     957            1 :     ClearWarningMsgContainerByWorkId(work_stream_id);
     958            1 : }
     959              : 
     960            1 : void ErrorManager::GenWorkStreamIdWithSessionIdGraphId(const uint64_t session_id, const uint64_t graph_id)
     961              : {
     962            1 :     constexpr uint64_t kSessionIdOffset = 100000UL;
     963            1 :     const uint64_t work_stream_id = (session_id * kSessionIdOffset) + graph_id;
     964            1 :     error_context_.work_stream_id = work_stream_id;
     965            1 : }
     966              : 
     967           54 : void ErrorManager::ClearErrorMsgContainerByWorkId(const uint64_t work_stream_id)
     968              : {
     969           54 :     return ClearMessageContainerByWorkId(error_message_per_work_id_, work_stream_id);
     970              : }
     971              : 
     972           12 : void ErrorManager::ClearWarningMsgContainerByWorkId(const uint64_t work_stream_id)
     973              : {
     974           12 :     return ClearMessageContainerByWorkId(warning_messages_per_work_id_, work_stream_id);
     975              : }
     976              : 
     977           58 : void ErrorManager::ClearErrorMsgContainer(const uint64_t work_stream_id)
     978              : {
     979           58 :     if (error_mode_.load(std::memory_order_acquire) == error_message::ErrorMsgMode::PROCESS_MODE) {
     980            6 :         error_message_process_.clear();
     981              :     } else {
     982           52 :         ClearErrorMsgContainerByWorkId(work_stream_id);
     983              :     }
     984           58 : }
     985              : 
     986           15 : void ErrorManager::ClearWarningMsgContainer(const uint64_t work_stream_id)
     987              : {
     988           15 :     if (error_mode_.load(std::memory_order_acquire) == error_message::ErrorMsgMode::PROCESS_MODE) {
     989            4 :         warning_messages_process_.clear();
     990              :     } else {
     991           11 :         ClearWarningMsgContainerByWorkId(work_stream_id);
     992              :     }
     993           15 : }
     994              : 
     995           26 : const std::string& ErrorManager::GetLogHeader()
     996              : {
     997           26 :     if ((error_context_.first_stage == "") && (error_context_.second_stage == "")) {
     998           26 :         error_context_.log_header = "";
     999              :     } else {
    1000            0 :         error_context_.log_header = "[" + error_context_.first_stage + "][" + error_context_.second_stage + "]";
    1001              :     }
    1002           26 :     return error_context_.log_header;
    1003              : }
    1004              : 
    1005            3 : error_message::Context& ErrorManager::GetErrorManagerContext()
    1006              : {
    1007              :     // son thread need set father thread work_stream_id, but work_stream_id cannot be zero
    1008              :     // so GenWorkStreamIdDefault here directly
    1009            3 :     if (error_context_.work_stream_id == 0UL) {
    1010            1 :         GenWorkStreamIdDefault();
    1011              :     }
    1012            3 :     return error_context_;
    1013              : }
    1014              : 
    1015            4 : void ErrorManager::SetErrorContext(error_message::Context error_context)
    1016              : {
    1017            4 :     error_context_.work_stream_id = error_context.work_stream_id;
    1018            8 :     error_context_.first_stage = std::move(error_context.first_stage);
    1019            8 :     error_context_.second_stage = std::move(error_context.second_stage);
    1020            8 :     error_context_.log_header = std::move(error_context.log_header);
    1021            4 : }
    1022              : 
    1023            0 : void ErrorManager::SetStage(const std::string& first_stage, const std::string& second_stage)
    1024              : {
    1025            0 :     error_context_.first_stage = first_stage;
    1026            0 :     error_context_.second_stage = second_stage;
    1027            0 : }
    1028              : 
    1029           83 : bool ErrorManager::IsInnerErrorCode(const std::string& error_code) const
    1030              : {
    1031           83 :     const std::string kInterErrorCodePrefix = "9999";
    1032           83 :     if (!IsValidErrorCode(error_code)) {
    1033            7 :         return false;
    1034              :     } else {
    1035           76 :         return (error_code.substr(2U, 4U) == kInterErrorCodePrefix) || IsParamCheckErrorId(error_code);
    1036              :     }
    1037           83 : }
    1038              : 
    1039              : // 这里只做简单校验, 校验是非内部错误码、非预定义错误码的6位字符串即可
    1040           13 : bool ErrorManager::IsUserDefinedErrorCode(const std::string& error_code)
    1041              : {
    1042           13 :     if (!IsValidErrorCode(error_code) || IsInnerErrorCode(error_code)) {
    1043            7 :         return false;
    1044              :     }
    1045              : 
    1046            6 :     if (EnsureInitialized() != 0) {
    1047            1 :         GELOGI("ErrorManager has not been initialized, can't verify error code.");
    1048            1 :         return false;
    1049              :     }
    1050              : 
    1051            5 :     const std::unique_lock<std::mutex> lck(mutex_);
    1052            5 :     if (error_map_.find(error_code) != error_map_.end()) {
    1053            2 :         GELOGW("Report error_code:[%s] is predefined error code, suggested use U error code", error_code.c_str());
    1054            2 :         return false;
    1055              :     }
    1056            3 :     return true;
    1057            5 : }
    1058              : 
    1059           83 : bool ErrorManager::IsParamCheckErrorId(const std::string& error_code) const
    1060              : {
    1061           83 :     return (error_code.substr(2U, 4U) == kParamCheckErrorSuffix);
    1062              : }
    1063              : 
    1064            1 : int32_t ErrorManager::SetRawErrorMessages(const std::vector<ErrorItem>& items)
    1065              : {
    1066            1 :     const std::unique_lock<std::mutex> lck(mutex_);
    1067            1 :     if (error_context_.work_stream_id == 0UL) {
    1068            1 :         GenWorkStreamIdDefault();
    1069              :     }
    1070              : 
    1071            1 :     GELOGI("Set error_message, work_stream_id:%lu.", error_context_.work_stream_id);
    1072            1 :     auto& error_messages = GetErrorMsgContainer(error_context_.work_stream_id);
    1073            2 :     (void)error_messages.insert(error_messages.end(), items.begin(), items.end());
    1074            1 :     return 0;
    1075            1 : }
    1076              : 
    1077           37 : std::vector<error_message::ErrorItem> ErrorManager::GetRawErrorMessages()
    1078              : {
    1079           37 :     GELOGI("current work_stream_id:%lu", error_context_.work_stream_id);
    1080           37 :     const std::unique_lock<std::mutex> lck(mutex_);
    1081           37 :     auto error_items = GetErrorMsgContainer(error_context_.work_stream_id);
    1082           37 :     ClearErrorMsgContainer(error_context_.work_stream_id);
    1083           37 :     return error_items;
    1084           37 : }
    1085              : 
    1086              : namespace error_message {
    1087          308 : int32_t RegisterFormatErrorMessage(const char_t* error_msg, size_t error_msg_len)
    1088              : {
    1089          308 :     nlohmann::json j;
    1090              :     try {
    1091          310 :         j = nlohmann::json::parse(error_msg, error_msg + error_msg_len);
    1092            2 :     } catch (const nlohmann::json::parse_error& e) {
    1093            2 :         return -1;
    1094            2 :     }
    1095          306 :     GELOGI("RegisterFormatErrorMessage, try to register error message");
    1096              :     // User registration error codes have high priority than those defined in the json file,
    1097              :     // set priority to 1 here.
    1098          306 :     return ErrorManager::GetInstance().ParseJsonFormatString(PtrToPtr<nlohmann::json, void>(&j), 1);
    1099          308 : }
    1100              : 
    1101            6 : int32_t ReportInnerErrMsg(
    1102              :     const char* file_name, const char* func, uint32_t line, const char* error_code, const char* format, ...)
    1103              : {
    1104              :     va_list arg_list;
    1105            6 :     va_start(arg_list, format);
    1106            6 :     const auto ret = ReportInnerErrorMessage(file_name, func, line, error_code, format, arg_list);
    1107            6 :     va_end(arg_list);
    1108            6 :     return ret;
    1109              : }
    1110              : 
    1111            9 : int32_t ReportUserDefinedErrMsg(const char* error_code, const char* format, ...)
    1112              : {
    1113              :     va_list arg_list;
    1114            9 :     std::vector<char> buf(LIMIT_PER_MESSAGE, '\0');
    1115            9 :     va_start(arg_list, format);
    1116            9 :     const auto ret = vsprintf_s(buf.data(), LIMIT_PER_MESSAGE, format, arg_list);
    1117            9 :     if (ret < 0) {
    1118            1 :         GELOGE("[Check][Param] Format error message failed, ret:%d", ret);
    1119            1 :         return -1;
    1120              :     }
    1121              : 
    1122           40 :     return ErrorManager::GetInstance().ReportErrMsgWithoutTpl(error_code, std::string(buf.data()));
    1123            9 : }
    1124              : 
    1125           11 : int32_t ReportPredefinedErrMsg(
    1126              :     const char* error_code, const std::vector<const char*>& key, const std::vector<const char*>& value)
    1127              : {
    1128           11 :     if (key.size() != value.size()) {
    1129            1 :         GELOGE(
    1130              :             "[Check][Param] ReportPredefinedErrMsg failed, vector key size:[%zu] and value size:[%zu] is not equal",
    1131              :             key.size(), value.size());
    1132            1 :         return -1;
    1133              :     }
    1134           10 :     std::map<std::string, std::string> args_map;
    1135           28 :     for (size_t i = 0UL; i < key.size(); ++i) {
    1136           18 :         (void)args_map.insert(std::make_pair(key[i], value[i]));
    1137              :     }
    1138           20 :     return ErrorManager::GetInstance().ReportErrMessage(error_code, args_map);
    1139           10 : }
    1140              : 
    1141            1 : int32_t ReportPredefinedErrMsg(const char* error_code) { return ReportPredefinedErrMsg(error_code, {}, {}); }
    1142              : 
    1143            1 : int32_t ErrMgrInit(ErrorMessageMode error_mode)
    1144              : {
    1145            1 :     return ErrorManager::GetInstance().Init(static_cast<error_message::ErrorMsgMode>(error_mode));
    1146              : }
    1147              : 
    1148            1 : ErrorManagerContext GetErrMgrContext()
    1149              : {
    1150            1 :     auto ctx = ErrorManager::GetInstance().GetErrorManagerContext();
    1151            1 :     ErrorManagerContext error_context{};
    1152            1 :     error_context.work_stream_id = ctx.work_stream_id;
    1153            2 :     return error_context;
    1154            1 : }
    1155              : 
    1156            3 : void SetErrMgrContext(ErrorManagerContext error_context)
    1157              : {
    1158            3 :     Context ctx;
    1159            3 :     ctx.work_stream_id = error_context.work_stream_id;
    1160            6 :     return ErrorManager::GetInstance().SetErrorContext(ctx);
    1161            3 : }
    1162              : 
    1163           23 : unique_const_char_array GetErrMgrErrorMessage()
    1164              : {
    1165           23 :     return CreateUniquePtrFromString(ErrorManager::GetInstance().GetErrorMessage());
    1166              : }
    1167              : 
    1168            9 : unique_const_char_array GetErrMgrWarningMessage()
    1169              : {
    1170            9 :     return CreateUniquePtrFromString(ErrorManager::GetInstance().GetWarningMessage());
    1171              : }
    1172              : 
    1173            1 : std::vector<ErrMsgRawItem> GetErrMgrRawErrorMessages()
    1174              : {
    1175            1 :     std::vector<ErrMsgRawItem> raw_items;
    1176            1 :     auto error_items = ErrorManager::GetInstance().GetRawErrorMessages();
    1177            3 :     for (const auto& item : error_items) {
    1178            1 :         ErrMsgRawItem raw_item;
    1179            1 :         raw_item.error_id = CreateUniquePtrFromString(item.error_id);
    1180            1 :         raw_item.error_title = CreateUniquePtrFromString(item.error_title);
    1181            1 :         raw_item.error_message = CreateUniquePtrFromString(item.error_message);
    1182            1 :         raw_item.possible_cause = CreateUniquePtrFromString(item.possible_cause);
    1183            1 :         raw_item.solution = CreateUniquePtrFromString(item.solution);
    1184            4 :         for (const auto& arg : item.args_map) {
    1185            3 :             raw_item.args_key.emplace_back(CreateUniquePtrFromString(arg.first));
    1186            3 :             raw_item.args_value.emplace_back(CreateUniquePtrFromString(arg.second));
    1187              :         }
    1188            1 :         raw_item.report_time = CreateUniquePtrFromString(item.report_time);
    1189            1 :         raw_items.emplace_back(std::move(raw_item));
    1190            1 :     }
    1191            1 :     return raw_items;
    1192            1 : }
    1193              : } // namespace error_message
    1194              : 
    1195              : extern "C" {
    1196            3 : int32_t RegisterFormatErrorMessageForC(const char* error_msg, unsigned long error_msg_len)
    1197              : {
    1198            3 :     if (error_msg == nullptr) {
    1199            1 :         GELOGE("[Check][Param] error_msg is null");
    1200            1 :         return -1;
    1201              :     }
    1202              :     try {
    1203            2 :         return error_message::RegisterFormatErrorMessage(error_msg, error_msg_len);
    1204            0 :     } catch (const std::exception& e) {
    1205            0 :         GELOGE("[Check][Exception] RegisterFormatErrorMessageForC caught exception: %s", e.what());
    1206            0 :         return -1;
    1207            0 :     } catch (...) {
    1208            0 :         GELOGE("[Check][Exception] RegisterFormatErrorMessageForC caught unknown exception");
    1209            0 :         return -1;
    1210            0 :     }
    1211              : }
    1212              : 
    1213            8 : int32_t ReportPredefinedErrMsgForC(const char* error_code, const char** key, const char** value, unsigned long arg_num)
    1214              : {
    1215            8 :     if (error_code == nullptr) {
    1216            1 :         GELOGE("[Check][Param] error_code is null");
    1217            1 :         return -1;
    1218              :     }
    1219            7 :     if ((arg_num != 0U) && ((key == nullptr) || (value == nullptr))) {
    1220            3 :         GELOGE("[Check][Param] Argument arrays are null when arg_num:[%lu]", arg_num);
    1221            3 :         return -1;
    1222              :     }
    1223              : 
    1224            9 :     for (size_t i = 0U; i < arg_num; ++i) {
    1225            7 :         if ((key[i] == nullptr) || (value[i] == nullptr)) {
    1226            2 :             GELOGE("[Check][Param] Argument array contains null entry at index:[%zu]", i);
    1227            2 :             return -1;
    1228              :         }
    1229              :     }
    1230              : 
    1231              :     try {
    1232            2 :         std::vector<const char*> key_vec;
    1233            2 :         std::vector<const char*> value_vec;
    1234            2 :         key_vec.reserve(arg_num);
    1235            2 :         value_vec.reserve(arg_num);
    1236            5 :         for (size_t i = 0U; i < arg_num; ++i) {
    1237            3 :             key_vec.push_back(key[i]);
    1238            3 :             value_vec.push_back(value[i]);
    1239              :         }
    1240            2 :         return error_message::ReportPredefinedErrMsg(error_code, key_vec, value_vec);
    1241            2 :     } catch (const std::exception& e) {
    1242            0 :         GELOGE("[Check][Exception] ReportPredefinedErrMsgForC caught exception: %s", e.what());
    1243            0 :         return -1;
    1244            0 :     } catch (...) {
    1245            0 :         GELOGE("[Check][Exception] ReportPredefinedErrMsgForC caught unknown exception");
    1246            0 :         return -1;
    1247            0 :     }
    1248              : }
    1249              : 
    1250            6 : int32_t ReportInnerErrMsgForC(
    1251              :     const char* file_name, const char* func, uint32_t line, const char* error_code, const char* format, ...)
    1252              : {
    1253            6 :     if ((file_name == nullptr) || (func == nullptr) || (error_code == nullptr) || (format == nullptr)) {
    1254            4 :         GELOGE("[Check][Param] file_name or func or error_code or format is null");
    1255            4 :         return -1;
    1256              :     }
    1257              : 
    1258              :     va_list arg_list;
    1259            2 :     va_start(arg_list, format);
    1260            2 :     int32_t ret = -1;
    1261              :     try {
    1262            2 :         ret = ReportInnerErrorMessage(file_name, func, line, error_code, format, arg_list);
    1263            0 :     } catch (const std::exception& e) {
    1264            0 :         GELOGE("[Check][Exception] ReportInnerErrMsgForC caught exception: %s", e.what());
    1265            0 :     } catch (...) {
    1266            0 :         GELOGE("[Check][Exception] ReportInnerErrMsgForC caught unknown exception");
    1267            0 :     }
    1268            2 :     va_end(arg_list);
    1269            2 :     return ret;
    1270              : }
    1271              : } // extern "C"
        

Generated by: LCOV version 2.0-1