LCOV - code coverage report
Current view: top level - src/dfx/error_manager - error_manager.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 90.0 % 700 630
Test Date: 2026-07-28 10:52:34 Functions: 95.9 % 73 70

            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           78 : inline TO* PtrToPtr(TI* const ptr)
      28              : {
      29           78 :     return reinterpret_cast<TO*>(ptr);
      30              : }
      31              : 
      32              : template <typename TI, typename TO>
      33           75 : inline const TO* PtrToPtr(const TI* const ptr)
      34              : {
      35           75 :     return reinterpret_cast<const TO*>(ptr);
      36              : }
      37              : 
      38              : namespace {
      39              : const std::string kParamCheckErrorSuffix = "8888";
      40              : class GeLog {
      41              : public:
      42           25 :     static uint64_t GetTid()
      43              :     {
      44              : #ifdef __GNUC__
      45           25 :         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           25 :         return tid;
      50              :     }
      51              : };
      52              : 
      53        26273 : inline bool IsLogEnable(const int32_t module_name, const int32_t log_level)
      54              : {
      55        26273 :     const int32_t enable = CheckLogLevel(module_name, log_level);
      56              :     // 1:enable, 0:disable
      57        26273 :     return (enable == 1);
      58              : }
      59              : 
      60           75 : std::string CurrentTimeFormatStr()
      61              : {
      62           75 :     std::string time_str;
      63           75 :     auto now = std::chrono::system_clock::now();
      64           75 :     auto milli_seconds = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
      65           75 :     auto micro_seconds = std::chrono::time_point_cast<std::chrono::microseconds>(now);
      66           75 :     const auto now_t = std::chrono::system_clock::to_time_t(now);
      67           75 :     const std::tm* tm_now = std::localtime(&now_t);
      68           75 :     if (tm_now == nullptr) {
      69            0 :         return time_str;
      70              :     }
      71              : 
      72           75 :     constexpr int32_t year_base = 1900;
      73           75 :     constexpr size_t kMaxTimeLen = 128U;
      74           75 :     constexpr int64_t kOneThousandMs = 1000L;
      75           75 :     error_message::char_t format_time[kMaxTimeLen] = {};
      76          150 :     (void)snprintf_s(
      77              :         format_time, kMaxTimeLen, kMaxTimeLen - 1U, "%04d-%02d-%02d-%02d:%02d:%02d.%03ld.%03ld",
      78           75 :         tm_now->tm_year + year_base, tm_now->tm_mon + 1, tm_now->tm_mday, tm_now->tm_hour, tm_now->tm_min,
      79           75 :         tm_now->tm_sec, milli_seconds.time_since_epoch().count() % kOneThousandMs,
      80           75 :         micro_seconds.time_since_epoch().count() % kOneThousandMs);
      81           75 :     time_str = format_time;
      82           75 :     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          139 : std::vector<ErrorManager::ErrorItem>& GetOrCreateMessageContainerByWorkId(
     166              :     std::map<uint64_t, std::vector<ErrorManager::ErrorItem>>& message_container, uint64_t work_id)
     167              : {
     168          139 :     auto iter = message_container.find(work_id);
     169          139 :     if (iter == message_container.end()) {
     170           60 :         (void)message_container.emplace(work_id, std::vector<ErrorManager::ErrorItem>());
     171           60 :         iter = message_container.find(work_id);
     172              :     }
     173          278 :     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        58325 : void Ltrim(std::string& s)
     261              : {
     262        58325 :     (void)s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](const error_message::char_t c) -> bool {
     263        68438 :                       return static_cast<bool>(std::isspace(static_cast<uint8_t>(c)) == 0);
     264              :                   }));
     265        58325 : }
     266              : 
     267        58325 : void Rtrim(std::string& s)
     268              : {
     269       116650 :     (void)s.erase(
     270        58325 :         std::find_if(
     271        58325 :             s.rbegin(), s.rend(),
     272        58389 :             [](const error_message::char_t c) -> bool {
     273        58389 :                 return static_cast<bool>(std::isspace(static_cast<uint8_t>(c)) == 0);
     274              :             })
     275              :             .base(),
     276              :         s.end());
     277        58325 : }
     278              : 
     279              : /// @ingroup domi_common
     280              : /// @brief trim space
     281        58325 : void Trim(std::string& s)
     282              : {
     283        58325 :     Rtrim(s);
     284        58325 :     Ltrim(s);
     285        58325 : }
     286              : 
     287              : /// @brief Obtain error manager self library path
     288              : /// @return store liberror_manager.so path
     289            4 : std::string GetSelfLibraryDir(void)
     290              : {
     291            4 :     mmDlInfo dl_info{nullptr, nullptr, nullptr, nullptr, 0, 0, 0};
     292            4 :     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            4 :         std::string so_path = dl_info.dli_fname;
     299            4 :         error_message::char_t path[MMPA_MAX_PATH] = {};
     300            4 :         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            4 :         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            4 :         so_path = &(path[0]);
     310            4 :         so_path = so_path.substr(0U, so_path.rfind(kSeparator) + 1U);
     311            4 :         return so_path;
     312            4 :     }
     313              : }
     314              : 
     315              : // split string
     316        25930 : std::vector<std::string> SplitByDelim(const std::string& str, const error_message::char_t delim)
     317              : {
     318        25930 :     std::vector<std::string> elems;
     319              : 
     320        25930 :     if (str.empty()) {
     321         3264 :         elems.emplace_back("");
     322         3264 :         return elems;
     323              :     }
     324              : 
     325        22666 :     std::stringstream ss(str);
     326        22666 :     std::string item;
     327              : 
     328        80991 :     while (getline(ss, item, delim)) {
     329        58325 :         Trim(item);
     330        58325 :         elems.push_back(item);
     331              :     }
     332        22666 :     const auto str_size = str.size();
     333        22666 :     if ((str_size > 0U) && (str[str_size - 1U] == delim)) {
     334            0 :         elems.emplace_back("");
     335              :     }
     336              : 
     337        22666 :     return elems;
     338        22666 : }
     339              : } // namespace
     340              : 
     341              : thread_local error_message::Context ErrorManager::error_context_ = {0UL, "", "", ""};
     342              : 
     343              : /// @brief Obtain ErrorManager instance
     344              : /// @return ErrorManager instance
     345          519 : ErrorManager& ErrorManager::GetInstance()
     346              : {
     347          519 :     static ErrorManager instance;
     348          519 :     return instance;
     349              : }
     350              : 
     351              : /// @brief init
     352              : /// @param [in] path: current so path
     353              : /// @return int 0(success) -1(fail)
     354            6 : int32_t ErrorManager::Init(const std::string path)
     355              : {
     356            6 :     const std::unique_lock<std::mutex> lck(mutex_);
     357            6 :     const std::string file_path = path + kErrorCodePath;
     358            6 :     GELOGI("Begin to init, path is %s", path.c_str());
     359            6 :     const int32_t ret = ParseJsonFile(file_path);
     360            6 :     if (ret != 0) {
     361            6 :         GELOGW("[Parse][File]Parse config file:%s failed", file_path.c_str());
     362            6 :         return -1;
     363              :     }
     364            0 :     is_init_ = true;
     365            0 :     return 0;
     366            6 : }
     367              : 
     368              : /// @brief init
     369              : /// @return int 0(success) -1(fail)
     370            3 : int32_t ErrorManager::Init() { return Init(GetSelfLibraryDir()); }
     371              : 
     372            3 : int32_t ErrorManager::Init(error_message::ErrorMsgMode error_mode)
     373              : {
     374            3 :     if (error_mode >= error_message::ErrorMsgMode::ERR_MSG_MODE_MAX) {
     375            2 :         GELOGE("[Init][Error]error mode is invalid %u", error_mode);
     376            2 :         return -1;
     377              :     }
     378            1 :     error_mode_ = error_mode;
     379            1 :     return Init(GetSelfLibraryDir());
     380              : }
     381              : 
     382           29 : int32_t ErrorManager::ReportInterErrMessage(const std::string error_code, const std::string& error_msg)
     383              : {
     384           29 :     std::string report_time = CurrentTimeFormatStr();
     385           29 :     constexpr uint64_t kMaxWorkSize = 1000UL;
     386           29 :     if (!is_init_) {
     387            0 :         const int32_t kRetInit = Init();
     388            0 :         if (kRetInit == -1) {
     389            0 :             GELOGI("ErrorManager has not been initialized, can't report error_message.");
     390            0 :             return -1;
     391              :         }
     392              :     }
     393           29 :     if (!IsInnerErrorCode(error_code)) {
     394            2 :         GELOGE("[Report][Error]error_code %s is not internal error code", error_code.c_str());
     395            2 :         return -1;
     396              :     }
     397              : 
     398           27 :     const std::unique_lock<std::mutex> lck(mutex_);
     399           27 :     if (error_context_.work_stream_id == 0UL) {
     400            2 :         if (error_message_per_work_id_.size() > kMaxWorkSize) {
     401            1 :             GELOGW(
     402              :                 "[Report][Error]error_code %s, error work_stream total size exceed %lu, skip record",
     403              :                 error_code.c_str(), kMaxWorkSize);
     404            1 :             return -1;
     405              :         }
     406            1 :         GenWorkStreamIdDefault();
     407              :     }
     408              : 
     409           26 :     GELOGI(
     410              :         "report error_message, error_code:%s, work_stream_id:%lu, error_mode:%u", error_code.c_str(),
     411              :         error_context_.work_stream_id, error_mode_);
     412              : 
     413           26 :     auto& error_messages = GetErrorMsgContainer(error_context_.work_stream_id);
     414           26 :     auto& warning_messages = GetWarningMsgContainer(error_context_.work_stream_id);
     415              : 
     416           26 :     if (error_messages.size() > kMaxWorkSize) {
     417            1 :         GELOGW(
     418              :             "[Report][Error]error_code %s, error work_stream_id:%lu item size exceed %lu, skip record",
     419              :             error_code.c_str(), error_context_.work_stream_id, kMaxWorkSize);
     420            1 :         return -1;
     421              :     }
     422              : 
     423           25 :     std::string tmp = error_msg;
     424           25 :     if (error_mode_ == error_message::ErrorMsgMode::PROCESS_MODE) {
     425            8 :         tmp += "[THREAD:" + std::to_string(mmGetTid()) + "]";
     426              :     }
     427              : 
     428          100 :     ErrorManager::ErrorItem item = {error_code, "", tmp, "", "", {}, report_time};
     429           25 :     if (error_code[0UL] == 'W') {
     430           10 :         const auto it = find(warning_messages.begin(), warning_messages.end(), item);
     431           10 :         if (it == warning_messages.end()) {
     432           10 :             warning_messages.emplace_back(item);
     433              :         }
     434              :     } else {
     435           15 :         const auto it = find(error_messages.begin(), error_messages.end(), item);
     436           15 :         if (it == error_messages.end()) {
     437           15 :             error_messages.emplace_back(item);
     438              :         }
     439              :     }
     440           25 :     return 0;
     441           29 : }
     442              : 
     443              : /// @brief report error message
     444              : /// @param [in] error_code: error code
     445              : /// @param [in] args_map: parameter map
     446              : /// @return int 0(success) -1(fail)
     447           38 : int32_t ErrorManager::ReportErrMessage(const std::string error_code, const std::map<std::string, std::string>& args_map)
     448              : {
     449           38 :     std::string report_time = CurrentTimeFormatStr();
     450           38 :     if (!is_init_) {
     451            0 :         const int32_t kRetInit = Init();
     452            0 :         if (kRetInit == -1) {
     453            0 :             GELOGI("ErrorManager has not been initialized, can't report error_message.");
     454            0 :             return 0;
     455              :         }
     456              :     }
     457              : 
     458           38 :     if (error_context_.work_stream_id == 0UL) {
     459           10 :         GenWorkStreamIdDefault();
     460              :     }
     461              : 
     462           38 :     GELOGI(
     463              :         "report error_message, error_code:%s, work_stream_id:%lu, error_mode:%u.", error_code.c_str(),
     464              :         error_context_.work_stream_id, error_mode_);
     465           38 :     const std::map<std::string, ErrorManager::ErrorInfoConfig>::const_iterator iter = error_map_.find(error_code);
     466           38 :     if (iter == error_map_.cend()) {
     467            2 :         GELOGW("[Report][Warning]error_code %s is not registered", error_code.c_str());
     468            2 :         return -1;
     469              :     }
     470           36 :     const ErrorInfoConfig& error_info = iter->second;
     471           36 :     std::string error_message = error_info.error_message;
     472           74 :     for (const std::string& arg : error_info.arg_list) {
     473           45 :         if (arg.empty()) {
     474            4 :             GELOGI("arg is null");
     475            4 :             break;
     476              :         }
     477           41 :         const auto arg_it = args_map.find(arg);
     478           41 :         if (arg_it == args_map.end()) {
     479            2 :             GELOGE("[Report][Error]error_code: %s, arg %s does not exist in map", error_code.c_str(), arg.c_str());
     480            3 :             return -1;
     481              :         }
     482           39 :         const std::string& arg_value = arg_it->second;
     483           39 :         const auto index = error_message.find("%s");
     484           39 :         if (index == std::string::npos) {
     485            1 :             GELOGE(
     486              :                 "[Report][Error]error_code: %s, %s location in error_message is not found", error_code.c_str(),
     487              :                 arg.c_str());
     488            1 :             return -1;
     489              :         }
     490           38 :         (void)error_message.replace(index, kLength, arg_value);
     491              :     }
     492              : 
     493           33 :     const std::unique_lock<std::mutex> lock(mutex_);
     494           33 :     auto& error_messages = GetErrorMsgContainer(error_context_.work_stream_id);
     495           33 :     auto& warning_messages = GetWarningMsgContainer(error_context_.work_stream_id);
     496              : 
     497           33 :     if (error_mode_ == error_message::ErrorMsgMode::PROCESS_MODE) {
     498            8 :         error_message += "[THREAD:" + std::to_string(mmGetTid()) + "]";
     499              :     }
     500              :     ErrorManager::ErrorItem error_item = {
     501           99 :         error_code, error_info.error_title, error_message, error_info.possible_cause, error_info.solution, args_map,
     502           33 :         report_time};
     503           33 :     if (error_code[0UL] == 'W') {
     504           11 :         const auto it = find(warning_messages.begin(), warning_messages.end(), error_item);
     505           11 :         if (it == warning_messages.end()) {
     506           11 :             warning_messages.emplace_back(error_item);
     507              :         }
     508              :     } else {
     509           22 :         const auto it = find(error_messages.begin(), error_messages.end(), error_item);
     510           22 :         if (it == error_messages.end()) {
     511           18 :             error_messages.emplace_back(error_item);
     512              :         }
     513              :     }
     514           33 :     return 0;
     515           38 : }
     516              : 
     517            8 : int32_t ErrorManager::ReportErrMsgWithoutTpl(const std::string& error_code, const std::string& errmsg)
     518              : {
     519            8 :     std::string report_time = CurrentTimeFormatStr();
     520            8 :     if (!is_init_) {
     521            1 :         const auto ret = Init();
     522            1 :         if (ret == -1) {
     523            1 :             GELOGI("ErrorManager has not been initialized, can't report error_message.");
     524            1 :             return -1;
     525              :         }
     526              :     }
     527              : 
     528            7 :     if (error_context_.work_stream_id == 0UL) {
     529            1 :         GenWorkStreamIdDefault();
     530              :     }
     531              : 
     532            7 :     auto final_error_code = error_code;
     533            7 :     if (!IsUserDefinedErrorCode(final_error_code)) {
     534            5 :         GELOGW(
     535              :             "[Report] Current error code is [%s], suggest using the recommended U segment. "
     536              :             "The error code EU0000 is reported!",
     537              :             final_error_code.c_str());
     538            5 :         final_error_code = "EU0000";
     539              :     }
     540              : 
     541            7 :     GELOGI(
     542              :         "report error_message, error_code:%s, work_stream_id:%lu, error_mode:%u.", error_code.c_str(),
     543              :         error_context_.work_stream_id, error_mode_);
     544              : 
     545            7 :     const std::unique_lock<std::mutex> lock(mutex_);
     546            7 :     auto& error_messages = GetErrorMsgContainer(error_context_.work_stream_id);
     547              : 
     548           28 :     ErrorItem error_item{final_error_code, "", errmsg, "", "", {}, report_time};
     549            7 :     const auto it = find(error_messages.begin(), error_messages.end(), error_item);
     550            7 :     if (it == error_messages.end()) {
     551            7 :         error_messages.emplace_back(error_item);
     552              :     }
     553            7 :     return 0;
     554            8 : }
     555              : 
     556            4 : void ErrorManager::AssembleInnerErrorMessage(
     557              :     const std::vector<ErrorItem>& error_messages, const std::string& first_code, std::stringstream& err_stream) const
     558              : {
     559            4 :     std::string current_code_print = first_code;
     560            4 :     const bool IsErrorId = IsParamCheckErrorId(first_code);
     561            8 :     for (auto& item : error_messages) {
     562            6 :         if (!IsParamCheckErrorId(item.error_id)) {
     563            2 :             current_code_print = item.error_id;
     564            2 :             break;
     565              :         }
     566              :     }
     567            4 :     err_stream << current_code_print << ": Internal error!" << std::endl;
     568            4 :     bool print_traceback_once = false;
     569           10 :     for (auto& item : error_messages) { // Display the first non 8888 error code
     570            6 :         if (IsParamCheckErrorId(item.error_id) && IsErrorId) {
     571            4 :             err_stream << "        " << item.error_message << std::endl;
     572            4 :             continue;
     573              :         }
     574            2 :         current_code_print == "      " ?
     575            0 :             (err_stream << current_code_print << " " << item.error_message << std::endl) :
     576            4 :             (err_stream << current_code_print << "[PID: " << std::to_string(mmGetPid()) << "] " << item.report_time
     577            4 :                         << " " << item.error_title << "(" << item.error_id << "): "
     578            4 :                         << " " << item.error_message << std::endl);
     579              : 
     580            2 :         current_code_print = "      ";
     581            2 :         if (!print_traceback_once) {
     582            2 :             err_stream << "TraceBack (most recent call last):" << std::endl;
     583            2 :             print_traceback_once = true;
     584              :         }
     585              :     }
     586            4 : }
     587              : 
     588           36 : std::string ErrorManager::GetErrorMessage()
     589              : {
     590           36 :     const auto& error_messages = GetRawErrorMessages();
     591           36 :     if (error_messages.empty()) {
     592           30 :         return "";
     593              :     }
     594              : 
     595           21 :     std::stringstream err_stream;
     596           21 :     std::string first_code = error_messages[0UL].error_id;
     597           27 :     for (const auto& item : error_messages) {
     598           23 :         if (!IsInnerErrorCode(item.error_id)) {
     599           17 :             first_code = item.error_id;
     600           34 :             err_stream << "[PID: " << std::to_string(mmGetPid()) << "] " << item.report_time << " " << item.error_title
     601           34 :                        << "(" << first_code << "): " << item.error_message << std::endl;
     602           17 :             if (!item.possible_cause.empty() && item.possible_cause != "N/A") {
     603            1 :                 err_stream << "        Possible Cause: " << item.possible_cause << std::endl;
     604              :             }
     605           17 :             if (!item.solution.empty() && item.solution != "N/A") {
     606            5 :                 err_stream << "        Solution: " << item.solution << std::endl;
     607              :             }
     608           17 :             break;
     609              :         }
     610              :     }
     611           21 :     if (IsInnerErrorCode(first_code)) {
     612            4 :         AssembleInnerErrorMessage(error_messages, first_code, err_stream);
     613              :     } else {
     614           17 :         bool print_traceback_once = false;
     615           49 :         for (const auto& item : error_messages) {
     616           32 :             if (first_code == item.error_id && error_messages[0].error_message == item.error_message) {
     617           18 :                 continue;
     618              :             }
     619           14 :             if (!print_traceback_once) {
     620            6 :                 err_stream << "TraceBack (most recent call last):" << std::endl;
     621            6 :                 print_traceback_once = true;
     622              :             }
     623           14 :             err_stream << "        " << item.error_message << std::endl;
     624              :         }
     625              :     }
     626           21 :     const std::unique_lock<std::mutex> lck(mutex_);
     627           21 :     ClearErrorMsgContainer(error_context_.work_stream_id);
     628           21 :     return err_stream.str();
     629           36 : }
     630              : 
     631           15 : std::string ErrorManager::GetWarningMessage()
     632              : {
     633           15 :     GELOGI("current work_stream_id:%lu, error_mode:%u", error_context_.work_stream_id, error_mode_);
     634           15 :     const std::unique_lock<std::mutex> lck(mutex_);
     635           15 :     auto& warning_messages = GetWarningMsgContainer(error_context_.work_stream_id);
     636              : 
     637           15 :     std::stringstream warning_stream;
     638           30 :     for (auto& item : warning_messages) {
     639           30 :         warning_stream << "[PID: " << std::to_string(mmGetPid()) << "] " << item.report_time << " " << item.error_title
     640           30 :                        << "(" << item.error_id << "): " << item.error_message << std::endl;
     641              :     }
     642           15 :     ClearWarningMsgContainer(error_context_.work_stream_id);
     643           30 :     return warning_stream.str();
     644           15 : }
     645              : 
     646              : /// @brief output error message
     647              : /// @param [in] handle: print handle
     648              : /// @return int 0(success) -1(fail)
     649            2 : int32_t ErrorManager::OutputErrMessage(int32_t handle)
     650              : {
     651            2 :     std::string err_msg = GetErrorMessage();
     652            2 :     if (err_msg.empty()) {
     653            2 :         std::stringstream err_stream;
     654            2 :         err_stream << "E19999: Internal error!" << std::endl;
     655              :         err_stream << "        "
     656            2 :                    << "Unknown error occurred. Please check the log." << std::endl;
     657            2 :         err_msg = err_stream.str();
     658            2 :     }
     659              : 
     660            2 :     if (handle <= fileno(stderr)) {
     661            1 :         std::cout << err_msg << std::endl;
     662              :     } else {
     663            1 :         const mmSsize_t ret = mmWrite(
     664            1 :             handle, const_cast<error_message::char_t*>(err_msg.c_str()), static_cast<uint32_t>(err_msg.length()));
     665            1 :         if (ret == -1) {
     666            1 :             GELOGE("[Write][File]fail, reason:%s", strerror(errno));
     667            1 :             return -1;
     668              :         }
     669              :     }
     670            1 :     return 0;
     671            2 : }
     672              : 
     673              : /// @brief output message
     674              : /// @param [in] handle: print handle
     675              : /// @return int 0(success) -1(fail)
     676            1 : int32_t ErrorManager::OutputMessage(int32_t handle)
     677              : {
     678            1 :     const std::string warning_msg = GetWarningMessage();
     679            1 :     std::cout << warning_msg << std::endl;
     680            1 :     handle = 0;
     681            1 :     return handle;
     682            1 : }
     683              : 
     684            7 : int32_t ErrorManager::ParseJsonFile(const std::string path)
     685              : {
     686            7 :     GELOGD("Begin to parse json file, path is %s", path.c_str());
     687            7 :     nlohmann::json json_file;
     688            7 :     const int32_t status = ReadJsonFile(path, &json_file);
     689            7 :     if (status != 0) {
     690            6 :         GELOGW("[Read][JsonFile]file path is %s", path.c_str());
     691            6 :         return -1;
     692              :     }
     693            1 :     return ParseJsonFormatString(PtrToPtr<nlohmann::json, void>(&json_file));
     694            7 : }
     695              : /// @brief parse json file
     696              : /// @param [in] handle: json handle
     697              : /// @return int 0(success) -1(fail)
     698           75 : int32_t ErrorManager::ParseJsonFormatString(const void* const handle, uint32_t priority)
     699              : {
     700           75 :     GELOGD("Begin to parse json string");
     701              :     try {
     702           75 :         const nlohmann::json* const json_file = PtrToPtr<void, nlohmann::json>(handle);
     703           75 :         if (json_file->find("error_info_list") == json_file->end()) {
     704            2 :             GELOGW("[Check][Config]The message of error_info_list is not found");
     705            2 :             return -1;
     706              :         }
     707           73 :         const nlohmann::json& error_list_json = json_file->at("error_info_list");
     708           73 :         if (error_list_json.is_null() || !error_list_json.is_array()) {
     709            1 :             GELOGW("[Check][Config]The message of error_info_list is not found or "
     710              :                    "the message of error_info_list is not array");
     711            1 :             return -1;
     712              :         }
     713        26002 :         for (const auto& error_json : error_list_json) {
     714        25931 :             ErrorInfoConfig error_info;
     715        25931 :             error_info.error_id = error_json["ErrCode"];
     716        25930 :             error_info.error_message = error_json["ErrMessage"];
     717        25930 :             if (error_json.contains("errTitle")) {
     718        23240 :                 error_info.error_title = error_json["errTitle"];
     719              :             }
     720        25930 :             if (error_json.contains("suggestion")) {
     721        10760 :                 error_info.possible_cause = error_json["suggestion"]["Possible Cause"];
     722        10760 :                 error_info.solution = error_json["suggestion"]["Solution"];
     723              :             }
     724        25930 :             error_info.arg_list = SplitByDelim(error_json["Arglist"], ',');
     725        25930 :             error_info.priority = priority;
     726        25930 :             auto it = error_map_.find(error_info.error_id);
     727        25930 :             if (it == error_map_.cend()) {
     728          414 :                 (void)error_map_.emplace(error_info.error_id, error_info);
     729          414 :                 GELOGD("add error_code %s success", error_info.error_id.c_str());
     730              :             } else {
     731        25516 :                 if (it->second.priority < error_info.priority) {
     732            0 :                     it->second = error_info;
     733            0 :                     GELOGD(
     734              :                         "Update error_code %s success, current priority[%u] is greater than saved priority[%u]",
     735              :                         error_info.error_id.c_str(), priority, it->second.priority);
     736              :                 } else {
     737        25516 :                     GELOGD(
     738              :                         "No need update error_code %s, due to current priority[%u] is less than "
     739              :                         "or equal to saved priority[%u]",
     740              :                         error_info.error_id.c_str(), priority, it->second.priority);
     741              :                 }
     742              :             }
     743        25931 :         }
     744            1 :     } catch (const nlohmann::json::exception& e) {
     745            1 :         GELOGW("[Parse][JsonFile]exception message: %s", e.what());
     746            1 :         return -1;
     747            1 :     }
     748           71 :     return 0;
     749              : }
     750              : 
     751              : /// @brief read json file
     752              : /// @param [in] file_path: json path
     753              : /// @param [in] handle:  print handle
     754              : /// @return int 0(success) -1(fail)
     755           79 : int32_t ErrorManager::ReadJsonFile(const std::string& file_path, void* const handle)
     756              : {
     757           79 :     if (file_path.empty()) {
     758            1 :         GELOGW("[Read][JsonFile]path %s is not valid", file_path.c_str());
     759            1 :         return -1;
     760              :     }
     761           78 :     nlohmann::json* const json_file = PtrToPtr<void, nlohmann::json>(handle);
     762           78 :     if (json_file == nullptr) {
     763            1 :         GELOGW("[Check][Param]JsonFile is nullptr");
     764            1 :         return -1;
     765              :     }
     766           77 :     const error_message::char_t* const file = file_path.data();
     767           77 :     if ((mmAccess2(file, M_F_OK)) != EN_OK) {
     768            6 :         GELOGW("[Read][JsonFile] %s does not exist, error %s", file_path.c_str(), strerror(errno));
     769            6 :         return -1;
     770              :     }
     771              : 
     772           71 :     std::ifstream ifs(file_path);
     773           71 :     if (!ifs.is_open()) {
     774            0 :         GELOGW("[Read][JsonFile]Open %s failed", file_path.c_str());
     775            0 :         return -1;
     776              :     }
     777              : 
     778           71 :     const std::string content((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
     779              :     try {
     780           72 :         *json_file = nlohmann::json::parse(content.c_str(), content.c_str() + content.size());
     781            1 :     } catch (const nlohmann::json::exception& e) {
     782            1 :         GELOGW("[Read][JsonFile]Parse json fail. path: %s, exception message: %s.", file_path.c_str(), e.what());
     783            1 :         ifs.close();
     784            1 :         return -1;
     785            1 :     }
     786              : 
     787           70 :     ifs.close();
     788           70 :     GELOGD("Read json file success");
     789           70 :     return 0;
     790           71 : }
     791              : 
     792              : /// @brief report error message
     793              : /// @param [in] error_code: error code
     794              : /// @param [in] vector parameter key, vector parameter value
     795              : /// @return int 0(success) -1(fail)
     796            4 : void ErrorManager::ATCReportErrMessage(
     797              :     const std::string error_code, const std::vector<std::string>& key, const std::vector<std::string>& value)
     798              : {
     799            4 :     if (!is_init_) {
     800            0 :         const int32_t kRetInit = Init();
     801            0 :         if (kRetInit == -1) {
     802            0 :             GELOGI("ErrorManager has not been initialized, can't report error_message.");
     803            0 :             return;
     804              :         }
     805              :     }
     806            4 :     std::map<std::string, std::string> args_map;
     807            4 :     if (key.empty()) {
     808            2 :         (void)ErrorManager::GetInstance().ReportErrMessage(error_code, args_map);
     809            2 :     } else if (key.size() == value.size()) {
     810            2 :         for (size_t i = 0UL; i < key.size(); ++i) {
     811            1 :             (void)args_map.insert(std::make_pair(key[i], value[i]));
     812              :         }
     813            1 :         (void)ErrorManager::GetInstance().ReportErrMessage(error_code, args_map);
     814              :     } else {
     815            1 :         GELOGW("ATCReportErrMessage wrong, vector key and value size is not equal");
     816              :     }
     817            4 : }
     818              : 
     819              : /// @brief report graph compile failed message such as error code and op_name in mustune case
     820              : /// @param [in] msg: failed message map, key is error code, value is op_name
     821              : /// @param [out] classified_msg: classified_msg message map, key is error code, value is op_name vector
     822            4 : void ErrorManager::ClassifyCompileFailedMsg(
     823              :     const std::map<std::string, std::string>& msg, std::map<std::string, std::vector<std::string>>& classified_msg)
     824              : {
     825            8 :     for (const auto& itr : msg) {
     826            4 :         GELOGD("msg is error_code:%s, op_name:%s", itr.first.c_str(), itr.second.c_str());
     827            4 :         const auto err_code_itr = classified_msg.find(itr.first);
     828            4 :         if (err_code_itr == classified_msg.end()) {
     829            9 :             (void)classified_msg.emplace(itr.first, std::vector<std::string>{itr.second});
     830              :         } else {
     831            1 :             std::vector<std::string>& op_name_list = err_code_itr->second;
     832            1 :             op_name_list.emplace_back(itr.second);
     833              :         }
     834              :     }
     835            7 : }
     836              : 
     837              : /// @brief report graph compile failed message such as error code and op_name in mustune case
     838              : /// @param [in] root_graph_name: root graph name
     839              : /// @param [in] msg: failed message map, key is error code, value is op_name
     840              : /// @return int 0(success) -1(fail)
     841            4 : int32_t ErrorManager::ReportMstuneCompileFailedMsg(
     842              :     const std::string& root_graph_name, const std::map<std::string, std::string>& msg)
     843              : {
     844            4 :     if (!is_init_) {
     845            0 :         const int32_t kRetInit = Init();
     846            0 :         if (kRetInit == -1) {
     847            0 :             GELOGI("ErrorManager has not been initialized, can't report error_message.");
     848            0 :             return 0;
     849              :         }
     850              :     }
     851            4 :     if (msg.empty() || root_graph_name.empty()) {
     852            2 :         GELOGW(
     853              :             "Msg or root graph name is empty, msg size is %zu, root graph name is %s", msg.size(),
     854              :             root_graph_name.c_str());
     855            2 :         return -1;
     856              :     }
     857            2 :     GELOGD("Report graph:%s compile failed msg", root_graph_name.c_str());
     858            2 :     const std::unique_lock<std::mutex> lock(mutex_);
     859            2 :     const auto itr = compile_failed_msg_map_.find(root_graph_name);
     860            2 :     if (itr != compile_failed_msg_map_.end()) {
     861            1 :         std::map<std::string, std::vector<std::string>>& classified_msg = itr->second;
     862            1 :         ClassifyCompileFailedMsg(msg, classified_msg);
     863              :     } else {
     864            1 :         std::map<std::string, std::vector<std::string>> classified_msg;
     865            1 :         ClassifyCompileFailedMsg(msg, classified_msg);
     866            1 :         (void)compile_failed_msg_map_.emplace(root_graph_name, classified_msg);
     867            1 :     }
     868            2 :     return 0;
     869            2 : }
     870              : 
     871              : /// @brief get graph compile failed message in mustune case
     872              : /// @param [in] graph_name: graph name
     873              : /// @param [out] msg_map: failed message map, key is error code, value is op_name list
     874              : /// @return int 0(success) -1(fail)
     875            4 : int32_t ErrorManager::GetMstuneCompileFailedMsg(
     876              :     const std::string& graph_name, std::map<std::string, std::vector<std::string>>& msg_map)
     877              : {
     878            4 :     if (!is_init_) {
     879            0 :         const int32_t kRetInit = Init();
     880            0 :         if (kRetInit == -1) {
     881            0 :             GELOGI("ErrorManager has not been initialized, can't report error_message.");
     882            0 :             return 0;
     883              :         }
     884              :     }
     885            4 :     if (!msg_map.empty()) {
     886            2 :         GELOGW("msg_map is not empty, exist msg");
     887            2 :         return -1;
     888              :     }
     889            2 :     const std::unique_lock<std::mutex> lock(mutex_);
     890            2 :     const auto iter = compile_failed_msg_map_.find(graph_name);
     891            2 :     if (iter == compile_failed_msg_map_.end()) {
     892            1 :         GELOGW("can not find graph, name is:%s", graph_name.c_str());
     893            1 :         return -1;
     894              :     } else {
     895            1 :         auto& compile_failed_msg = iter->second;
     896            1 :         msg_map.swap(compile_failed_msg);
     897            1 :         (void)compile_failed_msg_map_.erase(graph_name);
     898              :     }
     899            1 :     GELOGI("get graph:%s compile result msg success", graph_name.c_str());
     900              : 
     901            1 :     return 0;
     902            2 : }
     903              : 
     904           85 : std::vector<ErrorManager::ErrorItem>& ErrorManager::GetErrorMsgContainerByWorkId(uint64_t work_id)
     905              : {
     906           85 :     return GetOrCreateMessageContainerByWorkId(error_message_per_work_id_, work_id);
     907              : }
     908              : 
     909           54 : std::vector<ErrorManager::ErrorItem>& ErrorManager::GetWarningMsgContainerByWorkId(uint64_t work_id)
     910              : {
     911           54 :     return GetOrCreateMessageContainerByWorkId(warning_messages_per_work_id_, work_id);
     912              : }
     913              : 
     914          104 : std::vector<ErrorManager::ErrorItem>& ErrorManager::GetErrorMsgContainer(uint64_t work_stream_id)
     915              : {
     916          104 :     return (error_mode_ == error_message::ErrorMsgMode::INTERNAL_MODE) ? GetErrorMsgContainerByWorkId(work_stream_id) :
     917          104 :                                                                          error_message_process_;
     918              : }
     919              : 
     920           74 : std::vector<ErrorManager::ErrorItem>& ErrorManager::GetWarningMsgContainer(uint64_t work_stream_id)
     921              : {
     922           74 :     return (error_mode_ == error_message::ErrorMsgMode::INTERNAL_MODE) ?
     923           54 :                GetWarningMsgContainerByWorkId(work_stream_id) :
     924           74 :                warning_messages_process_;
     925              : }
     926              : 
     927           14 : void ErrorManager::GenWorkStreamIdDefault()
     928              : {
     929              :     // system getpid and gettid is always successful
     930           14 :     const int32_t pid = mmGetPid();
     931           14 :     const int32_t tid = mmGetTid();
     932              : 
     933           14 :     constexpr uint64_t kPidOffset = 100000UL;
     934           14 :     const uint64_t work_stream_id =
     935           14 :         static_cast<uint64_t>(static_cast<uint32_t>(pid) * kPidOffset) + static_cast<uint64_t>(tid);
     936           14 :     error_context_.work_stream_id = work_stream_id;
     937           14 : }
     938              : 
     939            1 : void ErrorManager::GenWorkStreamIdBySessionGraph(const uint64_t session_id, const uint64_t graph_id)
     940              : {
     941            1 :     constexpr uint64_t kSessionIdOffset = 100000UL;
     942            1 :     const uint64_t work_stream_id = (session_id * kSessionIdOffset) + graph_id;
     943            1 :     error_context_.work_stream_id = work_stream_id;
     944              : 
     945            1 :     const std::unique_lock<std::mutex> lck(mutex_);
     946            1 :     ClearErrorMsgContainerByWorkId(work_stream_id);
     947            1 :     ClearWarningMsgContainerByWorkId(work_stream_id);
     948            1 : }
     949              : 
     950            1 : void ErrorManager::GenWorkStreamIdWithSessionIdGraphId(const uint64_t session_id, const uint64_t graph_id)
     951              : {
     952            1 :     constexpr uint64_t kSessionIdOffset = 100000UL;
     953            1 :     const uint64_t work_stream_id = (session_id * kSessionIdOffset) + graph_id;
     954            1 :     error_context_.work_stream_id = work_stream_id;
     955            1 : }
     956              : 
     957           54 : void ErrorManager::ClearErrorMsgContainerByWorkId(const uint64_t work_stream_id)
     958              : {
     959           54 :     return ClearMessageContainerByWorkId(error_message_per_work_id_, work_stream_id);
     960              : }
     961              : 
     962           12 : void ErrorManager::ClearWarningMsgContainerByWorkId(const uint64_t work_stream_id)
     963              : {
     964           12 :     return ClearMessageContainerByWorkId(warning_messages_per_work_id_, work_stream_id);
     965              : }
     966              : 
     967           58 : void ErrorManager::ClearErrorMsgContainer(const uint64_t work_stream_id)
     968              : {
     969           58 :     if (error_mode_ == error_message::ErrorMsgMode::PROCESS_MODE) {
     970            6 :         error_message_process_.clear();
     971              :     } else {
     972           52 :         ClearErrorMsgContainerByWorkId(work_stream_id);
     973              :     }
     974           58 : }
     975              : 
     976           15 : void ErrorManager::ClearWarningMsgContainer(const uint64_t work_stream_id)
     977              : {
     978           15 :     if (error_mode_ == error_message::ErrorMsgMode::PROCESS_MODE) {
     979            4 :         warning_messages_process_.clear();
     980              :     } else {
     981           11 :         ClearWarningMsgContainerByWorkId(work_stream_id);
     982              :     }
     983           15 : }
     984              : 
     985           25 : const std::string& ErrorManager::GetLogHeader()
     986              : {
     987           25 :     if ((error_context_.first_stage == "") && (error_context_.second_stage == "")) {
     988           25 :         error_context_.log_header = "";
     989              :     } else {
     990            0 :         error_context_.log_header = "[" + error_context_.first_stage + "][" + error_context_.second_stage + "]";
     991              :     }
     992           25 :     return error_context_.log_header;
     993              : }
     994              : 
     995            3 : error_message::Context& ErrorManager::GetErrorManagerContext()
     996              : {
     997              :     // son thread need set father thread work_stream_id, but work_stream_id cannot be zero
     998              :     // so GenWorkStreamIdDefault here directly
     999            3 :     if (error_context_.work_stream_id == 0UL) {
    1000            1 :         GenWorkStreamIdDefault();
    1001              :     }
    1002            3 :     return error_context_;
    1003              : }
    1004              : 
    1005            4 : void ErrorManager::SetErrorContext(error_message::Context error_context)
    1006              : {
    1007            4 :     error_context_.work_stream_id = error_context.work_stream_id;
    1008            4 :     error_context_.first_stage = std::move(error_context.first_stage);
    1009            4 :     error_context_.second_stage = std::move(error_context.second_stage);
    1010            4 :     error_context_.log_header = std::move(error_context.log_header);
    1011            4 : }
    1012              : 
    1013            0 : void ErrorManager::SetStage(const std::string& first_stage, const std::string& second_stage)
    1014              : {
    1015            0 :     error_context_.first_stage = first_stage;
    1016            0 :     error_context_.second_stage = second_stage;
    1017            0 : }
    1018              : 
    1019           83 : bool ErrorManager::IsInnerErrorCode(const std::string& error_code) const
    1020              : {
    1021           83 :     const std::string kInterErrorCodePrefix = "9999";
    1022           83 :     if (!IsValidErrorCode(error_code)) {
    1023            7 :         return false;
    1024              :     } else {
    1025           76 :         return (error_code.substr(2U, 4U) == kInterErrorCodePrefix) || IsParamCheckErrorId(error_code);
    1026              :     }
    1027           83 : }
    1028              : 
    1029              : // 这里只做简单校验, 校验是非内部错误码、非预定义错误码的6位字符串即可
    1030           13 : bool ErrorManager::IsUserDefinedErrorCode(const std::string& error_code)
    1031              : {
    1032           13 :     if (!IsValidErrorCode(error_code) || IsInnerErrorCode(error_code)) {
    1033            7 :         return false;
    1034              :     }
    1035              : 
    1036            6 :     if (!is_init_) {
    1037            1 :         const auto ret = Init();
    1038            1 :         if (ret == -1) {
    1039            1 :             GELOGI("ErrorManager has not been initialized, can't verify error code.");
    1040            1 :             return false;
    1041              :         }
    1042              :     }
    1043              : 
    1044            5 :     if (error_map_.find(error_code) != error_map_.end()) {
    1045            2 :         GELOGW("Report error_code:[%s] is predefined error code, suggested use U error code", error_code.c_str());
    1046            2 :         return false;
    1047              :     }
    1048            3 :     return true;
    1049              : }
    1050              : 
    1051           83 : bool ErrorManager::IsParamCheckErrorId(const std::string& error_code) const
    1052              : {
    1053           83 :     return (error_code.substr(2U, 4U) == kParamCheckErrorSuffix);
    1054              : }
    1055              : 
    1056            1 : int32_t ErrorManager::SetRawErrorMessages(const std::vector<ErrorItem>& items)
    1057              : {
    1058            1 :     const std::unique_lock<std::mutex> lck(mutex_);
    1059            1 :     if (error_context_.work_stream_id == 0UL) {
    1060            1 :         GenWorkStreamIdDefault();
    1061              :     }
    1062              : 
    1063            1 :     GELOGI("Set error_message, work_stream_id:%lu.", error_context_.work_stream_id);
    1064            1 :     auto& error_messages = GetErrorMsgContainer(error_context_.work_stream_id);
    1065            1 :     (void)error_messages.insert(error_messages.end(), items.begin(), items.end());
    1066            1 :     return 0;
    1067            1 : }
    1068              : 
    1069           37 : std::vector<error_message::ErrorItem> ErrorManager::GetRawErrorMessages()
    1070              : {
    1071           37 :     GELOGI("current work_stream_id:%lu", error_context_.work_stream_id);
    1072           37 :     const std::unique_lock<std::mutex> lck(mutex_);
    1073           37 :     auto error_items = GetErrorMsgContainer(error_context_.work_stream_id);
    1074           37 :     ClearErrorMsgContainer(error_context_.work_stream_id);
    1075           37 :     return error_items;
    1076           37 : }
    1077              : 
    1078              : namespace error_message {
    1079            8 : int32_t RegisterFormatErrorMessage(const char_t* error_msg, size_t error_msg_len)
    1080              : {
    1081            8 :     nlohmann::json j;
    1082              :     try {
    1083           10 :         j = nlohmann::json::parse(error_msg, error_msg + error_msg_len);
    1084            2 :     } catch (const nlohmann::json::parse_error& e) {
    1085            2 :         return -1;
    1086            2 :     }
    1087            6 :     GELOGI("RegisterFormatErrorMessage, try to register error message");
    1088              :     // User registration error codes have high priority than those defined in the json file,
    1089              :     // set priority to 1 here.
    1090            6 :     return ErrorManager::GetInstance().ParseJsonFormatString(PtrToPtr<nlohmann::json, void>(&j), 1);
    1091            8 : }
    1092              : 
    1093            6 : int32_t ReportInnerErrMsg(
    1094              :     const char* file_name, const char* func, uint32_t line, const char* error_code, const char* format, ...)
    1095              : {
    1096              :     va_list arg_list;
    1097            6 :     va_start(arg_list, format);
    1098            6 :     const auto ret = ReportInnerErrorMessage(file_name, func, line, error_code, format, arg_list);
    1099            6 :     va_end(arg_list);
    1100            6 :     return ret;
    1101              : }
    1102              : 
    1103            9 : int32_t ReportUserDefinedErrMsg(const char* error_code, const char* format, ...)
    1104              : {
    1105              :     va_list arg_list;
    1106            9 :     std::vector<char> buf(LIMIT_PER_MESSAGE, '\0');
    1107            9 :     va_start(arg_list, format);
    1108            9 :     const auto ret = vsprintf_s(buf.data(), LIMIT_PER_MESSAGE, format, arg_list);
    1109            9 :     if (ret < 0) {
    1110            1 :         GELOGE("[Check][Param] Format error message failed, ret:%d", ret);
    1111            1 :         return -1;
    1112              :     }
    1113              : 
    1114           40 :     return ErrorManager::GetInstance().ReportErrMsgWithoutTpl(error_code, std::string(buf.data()));
    1115            9 : }
    1116              : 
    1117           11 : int32_t ReportPredefinedErrMsg(
    1118              :     const char* error_code, const std::vector<const char*>& key, const std::vector<const char*>& value)
    1119              : {
    1120           11 :     if (key.size() != value.size()) {
    1121            1 :         GELOGE(
    1122              :             "[Check][Param] ReportPredefinedErrMsg failed, vector key size:[%zu] and value size:[%zu] is not equal",
    1123              :             key.size(), value.size());
    1124            1 :         return -1;
    1125              :     }
    1126           10 :     std::map<std::string, std::string> args_map;
    1127           28 :     for (size_t i = 0UL; i < key.size(); ++i) {
    1128           18 :         (void)args_map.insert(std::make_pair(key[i], value[i]));
    1129              :     }
    1130           20 :     return ErrorManager::GetInstance().ReportErrMessage(error_code, args_map);
    1131           10 : }
    1132              : 
    1133            1 : int32_t ReportPredefinedErrMsg(const char* error_code) { return ReportPredefinedErrMsg(error_code, {}, {}); }
    1134              : 
    1135            1 : int32_t ErrMgrInit(ErrorMessageMode error_mode)
    1136              : {
    1137            1 :     return ErrorManager::GetInstance().Init(static_cast<error_message::ErrorMsgMode>(error_mode));
    1138              : }
    1139              : 
    1140            1 : ErrorManagerContext GetErrMgrContext()
    1141              : {
    1142            1 :     auto ctx = ErrorManager::GetInstance().GetErrorManagerContext();
    1143            1 :     ErrorManagerContext error_context{};
    1144            1 :     error_context.work_stream_id = ctx.work_stream_id;
    1145            2 :     return error_context;
    1146            1 : }
    1147              : 
    1148            3 : void SetErrMgrContext(ErrorManagerContext error_context)
    1149              : {
    1150            3 :     Context ctx;
    1151            3 :     ctx.work_stream_id = error_context.work_stream_id;
    1152            6 :     return ErrorManager::GetInstance().SetErrorContext(ctx);
    1153            3 : }
    1154              : 
    1155           23 : unique_const_char_array GetErrMgrErrorMessage()
    1156              : {
    1157           23 :     return CreateUniquePtrFromString(ErrorManager::GetInstance().GetErrorMessage());
    1158              : }
    1159              : 
    1160            9 : unique_const_char_array GetErrMgrWarningMessage()
    1161              : {
    1162            9 :     return CreateUniquePtrFromString(ErrorManager::GetInstance().GetWarningMessage());
    1163              : }
    1164              : 
    1165            1 : std::vector<ErrMsgRawItem> GetErrMgrRawErrorMessages()
    1166              : {
    1167            1 :     std::vector<ErrMsgRawItem> raw_items;
    1168            1 :     auto error_items = ErrorManager::GetInstance().GetRawErrorMessages();
    1169            2 :     for (const auto& item : error_items) {
    1170            1 :         ErrMsgRawItem raw_item;
    1171            1 :         raw_item.error_id = CreateUniquePtrFromString(item.error_id);
    1172            1 :         raw_item.error_title = CreateUniquePtrFromString(item.error_title);
    1173            1 :         raw_item.error_message = CreateUniquePtrFromString(item.error_message);
    1174            1 :         raw_item.possible_cause = CreateUniquePtrFromString(item.possible_cause);
    1175            1 :         raw_item.solution = CreateUniquePtrFromString(item.solution);
    1176            4 :         for (const auto& arg : item.args_map) {
    1177            3 :             raw_item.args_key.emplace_back(CreateUniquePtrFromString(arg.first));
    1178            3 :             raw_item.args_value.emplace_back(CreateUniquePtrFromString(arg.second));
    1179              :         }
    1180            1 :         raw_item.report_time = CreateUniquePtrFromString(item.report_time);
    1181            1 :         raw_items.emplace_back(std::move(raw_item));
    1182            1 :     }
    1183            1 :     return raw_items;
    1184            1 : }
    1185              : } // namespace error_message
    1186              : 
    1187              : extern "C" {
    1188            3 : int32_t RegisterFormatErrorMessageForC(const char* error_msg, unsigned long error_msg_len)
    1189              : {
    1190            3 :     if (error_msg == nullptr) {
    1191            1 :         GELOGE("[Check][Param] error_msg is null");
    1192            1 :         return -1;
    1193              :     }
    1194              :     try {
    1195            2 :         return error_message::RegisterFormatErrorMessage(error_msg, error_msg_len);
    1196            0 :     } catch (const std::exception& e) {
    1197            0 :         GELOGE("[Check][Exception] RegisterFormatErrorMessageForC caught exception: %s", e.what());
    1198            0 :         return -1;
    1199            0 :     } catch (...) {
    1200            0 :         GELOGE("[Check][Exception] RegisterFormatErrorMessageForC caught unknown exception");
    1201            0 :         return -1;
    1202            0 :     }
    1203              : }
    1204              : 
    1205            8 : int32_t ReportPredefinedErrMsgForC(const char* error_code, const char** key, const char** value, unsigned long arg_num)
    1206              : {
    1207            8 :     if (error_code == nullptr) {
    1208            1 :         GELOGE("[Check][Param] error_code is null");
    1209            1 :         return -1;
    1210              :     }
    1211            7 :     if ((arg_num != 0U) && ((key == nullptr) || (value == nullptr))) {
    1212            3 :         GELOGE("[Check][Param] Argument arrays are null when arg_num:[%lu]", arg_num);
    1213            3 :         return -1;
    1214              :     }
    1215              : 
    1216            9 :     for (size_t i = 0U; i < arg_num; ++i) {
    1217            7 :         if ((key[i] == nullptr) || (value[i] == nullptr)) {
    1218            2 :             GELOGE("[Check][Param] Argument array contains null entry at index:[%zu]", i);
    1219            2 :             return -1;
    1220              :         }
    1221              :     }
    1222              : 
    1223              :     try {
    1224            2 :         std::vector<const char*> key_vec;
    1225            2 :         std::vector<const char*> value_vec;
    1226            2 :         key_vec.reserve(arg_num);
    1227            2 :         value_vec.reserve(arg_num);
    1228            5 :         for (size_t i = 0U; i < arg_num; ++i) {
    1229            3 :             key_vec.push_back(key[i]);
    1230            3 :             value_vec.push_back(value[i]);
    1231              :         }
    1232            2 :         return error_message::ReportPredefinedErrMsg(error_code, key_vec, value_vec);
    1233            2 :     } catch (const std::exception& e) {
    1234            0 :         GELOGE("[Check][Exception] ReportPredefinedErrMsgForC caught exception: %s", e.what());
    1235            0 :         return -1;
    1236            0 :     } catch (...) {
    1237            0 :         GELOGE("[Check][Exception] ReportPredefinedErrMsgForC caught unknown exception");
    1238            0 :         return -1;
    1239            0 :     }
    1240              : }
    1241              : 
    1242            6 : int32_t ReportInnerErrMsgForC(
    1243              :     const char* file_name, const char* func, uint32_t line, const char* error_code, const char* format, ...)
    1244              : {
    1245            6 :     if ((file_name == nullptr) || (func == nullptr) || (error_code == nullptr) || (format == nullptr)) {
    1246            4 :         GELOGE("[Check][Param] file_name or func or error_code or format is null");
    1247            4 :         return -1;
    1248              :     }
    1249              : 
    1250              :     va_list arg_list;
    1251            2 :     va_start(arg_list, format);
    1252            2 :     int32_t ret = -1;
    1253              :     try {
    1254            2 :         ret = ReportInnerErrorMessage(file_name, func, line, error_code, format, arg_list);
    1255            0 :     } catch (const std::exception& e) {
    1256            0 :         GELOGE("[Check][Exception] ReportInnerErrMsgForC caught exception: %s", e.what());
    1257            0 :     } catch (...) {
    1258            0 :         GELOGE("[Check][Exception] ReportInnerErrMsgForC caught unknown exception");
    1259            0 :     }
    1260            2 :     va_end(arg_list);
    1261            2 :     return ret;
    1262              : }
    1263              : } // extern "C"
        

Generated by: LCOV version 2.0-1